Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/tabs/tab.h" | 5 #include "chrome/browser/ui/views/tabs/tab.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 #include "chrome/grit/generated_resources.h" | 27 #include "chrome/grit/generated_resources.h" |
| 28 #include "chrome/grit/theme_resources.h" | 28 #include "chrome/grit/theme_resources.h" |
| 29 #include "components/grit/components_scaled_resources.h" | 29 #include "components/grit/components_scaled_resources.h" |
| 30 #include "components/strings/grit/components_strings.h" | 30 #include "components/strings/grit/components_strings.h" |
| 31 #include "content/public/browser/user_metrics.h" | 31 #include "content/public/browser/user_metrics.h" |
| 32 #include "content/public/common/url_constants.h" | 32 #include "content/public/common/url_constants.h" |
| 33 #include "third_party/skia/include/effects/SkGradientShader.h" | 33 #include "third_party/skia/include/effects/SkGradientShader.h" |
| 34 #include "third_party/skia/include/pathops/SkPathOps.h" | 34 #include "third_party/skia/include/pathops/SkPathOps.h" |
| 35 #include "ui/accessibility/ax_view_state.h" | 35 #include "ui/accessibility/ax_view_state.h" |
| 36 #include "ui/base/l10n/l10n_util.h" | 36 #include "ui/base/l10n/l10n_util.h" |
| 37 #include "ui/base/material_design/material_design_controller.h" | |
| 38 #include "ui/base/models/list_selection_model.h" | 37 #include "ui/base/models/list_selection_model.h" |
| 39 #include "ui/base/resource/resource_bundle.h" | 38 #include "ui/base/resource/resource_bundle.h" |
| 40 #include "ui/base/theme_provider.h" | 39 #include "ui/base/theme_provider.h" |
| 41 #include "ui/gfx/animation/animation_container.h" | 40 #include "ui/gfx/animation/animation_container.h" |
| 42 #include "ui/gfx/animation/throb_animation.h" | 41 #include "ui/gfx/animation/throb_animation.h" |
| 43 #include "ui/gfx/canvas.h" | 42 #include "ui/gfx/canvas.h" |
| 44 #include "ui/gfx/color_analysis.h" | 43 #include "ui/gfx/color_analysis.h" |
| 45 #include "ui/gfx/favicon_size.h" | 44 #include "ui/gfx/favicon_size.h" |
| 46 #include "ui/gfx/geometry/rect_conversions.h" | 45 #include "ui/gfx/geometry/rect_conversions.h" |
| 47 #include "ui/gfx/image/image_skia_operations.h" | 46 #include "ui/gfx/image/image_skia_operations.h" |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 114 // Number of steps in the immersive mode loading animation. | 113 // Number of steps in the immersive mode loading animation. |
| 115 const int kImmersiveLoadingStepCount = 32; | 114 const int kImmersiveLoadingStepCount = 32; |
| 116 | 115 |
| 117 const char kTabCloseButtonName[] = "TabCloseButton"; | 116 const char kTabCloseButtonName[] = "TabCloseButton"; |
| 118 | 117 |
| 119 //////////////////////////////////////////////////////////////////////////////// | 118 //////////////////////////////////////////////////////////////////////////////// |
| 120 // ImageCacheEntryMetadata | 119 // ImageCacheEntryMetadata |
| 121 // | 120 // |
| 122 // All metadata necessary to uniquely identify a cached image. | 121 // All metadata necessary to uniquely identify a cached image. |
| 123 struct ImageCacheEntryMetadata { | 122 struct ImageCacheEntryMetadata { |
| 124 ImageCacheEntryMetadata(int resource_id, | 123 ImageCacheEntryMetadata(SkColor fill_color, |
| 125 SkColor fill_color, | |
| 126 SkColor stroke_color, | 124 SkColor stroke_color, |
| 127 bool use_fill_and_stroke_images, | 125 bool use_fill_and_stroke_images, |
| 128 float scale_factor, | 126 float scale_factor, |
| 129 const gfx::Size& size); | 127 const gfx::Size& size); |
| 130 | 128 |
| 131 ~ImageCacheEntryMetadata(); | 129 ~ImageCacheEntryMetadata(); |
| 132 | 130 |
| 133 bool operator==(const ImageCacheEntryMetadata& rhs) const; | 131 bool operator==(const ImageCacheEntryMetadata& rhs) const; |
| 134 | 132 |
| 135 int resource_id; // Only needed by pre-MD | 133 SkColor fill_color; |
| 136 SkColor fill_color; // Both colors only needed by MD | |
| 137 SkColor stroke_color; | 134 SkColor stroke_color; |
| 138 bool use_fill_and_stroke_images; | 135 bool use_fill_and_stroke_images; |
| 139 float scale_factor; | 136 float scale_factor; |
| 140 gfx::Size size; | 137 gfx::Size size; |
| 141 }; | 138 }; |
| 142 | 139 |
| 143 ImageCacheEntryMetadata::ImageCacheEntryMetadata( | 140 ImageCacheEntryMetadata::ImageCacheEntryMetadata( |
| 144 int resource_id, | |
| 145 SkColor fill_color, | 141 SkColor fill_color, |
| 146 SkColor stroke_color, | 142 SkColor stroke_color, |
| 147 bool use_fill_and_stroke_images, | 143 bool use_fill_and_stroke_images, |
| 148 float scale_factor, | 144 float scale_factor, |
| 149 const gfx::Size& size) | 145 const gfx::Size& size) |
| 150 : resource_id(resource_id), | 146 : fill_color(fill_color), |
| 151 fill_color(fill_color), | |
| 152 stroke_color(stroke_color), | 147 stroke_color(stroke_color), |
| 153 use_fill_and_stroke_images(use_fill_and_stroke_images), | 148 use_fill_and_stroke_images(use_fill_and_stroke_images), |
| 154 scale_factor(scale_factor), | 149 scale_factor(scale_factor), |
| 155 size(size) { | 150 size(size) {} |
| 156 // Some fields are only relevant for pre-MD vs. MD. Erase the irrelevant ones | |
| 157 // so they don't cause incorrect cache misses. | |
| 158 // TODO(pkasting): Remove |resource_id| field when non-MD code is deleted. | |
| 159 if (ui::MaterialDesignController::IsModeMaterial()) | |
| 160 resource_id = 0; | |
| 161 else | |
| 162 fill_color = stroke_color = SK_ColorTRANSPARENT; | |
| 163 } | |
| 164 | 151 |
| 165 ImageCacheEntryMetadata::~ImageCacheEntryMetadata() {} | 152 ImageCacheEntryMetadata::~ImageCacheEntryMetadata() {} |
| 166 | 153 |
| 167 bool ImageCacheEntryMetadata::operator==( | 154 bool ImageCacheEntryMetadata::operator==( |
| 168 const ImageCacheEntryMetadata& rhs) const { | 155 const ImageCacheEntryMetadata& rhs) const { |
| 169 return resource_id == rhs.resource_id && fill_color == rhs.fill_color && | 156 return fill_color == rhs.fill_color && stroke_color == rhs.stroke_color && |
| 170 stroke_color == rhs.stroke_color && | |
| 171 use_fill_and_stroke_images == rhs.use_fill_and_stroke_images && | 157 use_fill_and_stroke_images == rhs.use_fill_and_stroke_images && |
| 172 scale_factor == rhs.scale_factor && size == rhs.size; | 158 scale_factor == rhs.scale_factor && size == rhs.size; |
| 173 } | 159 } |
| 174 | 160 |
| 175 //////////////////////////////////////////////////////////////////////////////// | 161 //////////////////////////////////////////////////////////////////////////////// |
| 176 // ImageCacheEntry and cache management | 162 // ImageCacheEntry and cache management |
| 177 // | 163 // |
| 178 // A cached image and the metadata used to generate it. | 164 // A cached image and the metadata used to generate it. |
| 179 struct ImageCacheEntry { | 165 struct ImageCacheEntry { |
| 180 ImageCacheEntry(const ImageCacheEntryMetadata& metadata, | 166 ImageCacheEntry(const ImageCacheEntryMetadata& metadata, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 193 : metadata(metadata), fill_image(fill_image), stroke_image(stroke_image) {} | 179 : metadata(metadata), fill_image(fill_image), stroke_image(stroke_image) {} |
| 194 | 180 |
| 195 ImageCacheEntry::~ImageCacheEntry() {} | 181 ImageCacheEntry::~ImageCacheEntry() {} |
| 196 | 182 |
| 197 typedef std::list<ImageCacheEntry> ImageCache; | 183 typedef std::list<ImageCacheEntry> ImageCache; |
| 198 | 184 |
| 199 // As the majority of the tabs are inactive, and painting tabs is slowish, | 185 // As the majority of the tabs are inactive, and painting tabs is slowish, |
| 200 // we cache a handful of the inactive tab backgrounds here. | 186 // we cache a handful of the inactive tab backgrounds here. |
| 201 static ImageCache* g_image_cache = nullptr; | 187 static ImageCache* g_image_cache = nullptr; |
| 202 | 188 |
| 203 struct TabImages { | |
| 204 gfx::ImageSkia* image_l; | |
| 205 gfx::ImageSkia* image_c; | |
| 206 gfx::ImageSkia* image_r; | |
| 207 int l_width; | |
| 208 int r_width; | |
| 209 }; | |
| 210 static TabImages g_active_images = {0}; | |
| 211 static TabImages g_inactive_images = {0}; | |
| 212 static TabImages g_mask_images = {0}; | |
| 213 | |
| 214 // Loads the images to be used for the tab background. | |
| 215 void LoadTabImages() { | |
| 216 g_image_cache->clear(); | |
| 217 | |
| 218 // We're not letting people override tab images just yet. | |
| 219 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 220 | |
| 221 g_active_images.image_l = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_LEFT); | |
| 222 g_active_images.image_c = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_CENTER); | |
| 223 g_active_images.image_r = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_RIGHT); | |
| 224 g_active_images.l_width = g_active_images.image_l->width(); | |
| 225 g_active_images.r_width = g_active_images.image_r->width(); | |
| 226 | |
| 227 g_inactive_images.image_l = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_LEFT); | |
| 228 g_inactive_images.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); | |
| 229 g_inactive_images.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); | |
| 230 g_inactive_images.l_width = g_inactive_images.image_l->width(); | |
| 231 g_inactive_images.r_width = g_inactive_images.image_r->width(); | |
| 232 | |
| 233 g_mask_images.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); | |
| 234 g_mask_images.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); | |
| 235 g_mask_images.l_width = g_mask_images.image_l->width(); | |
| 236 g_mask_images.r_width = g_mask_images.image_r->width(); | |
| 237 } | |
| 238 | |
| 239 // Performs a one-time initialization of static resources such as tab images. | 189 // Performs a one-time initialization of static resources such as tab images. |
| 240 void InitTabResources() { | 190 void InitTabResources() { |
| 241 static bool initialized = false; | 191 static bool initialized = false; |
| 242 if (initialized) | 192 if (initialized) |
| 243 return; | 193 return; |
| 244 | 194 |
| 245 initialized = true; | 195 initialized = true; |
| 246 g_image_cache = new ImageCache(); | 196 g_image_cache = new ImageCache(); |
| 247 | |
| 248 // Load the tab images once now, and maybe again later if the theme changes. | |
| 249 LoadTabImages(); | |
| 250 } | 197 } |
| 251 | 198 |
| 252 //////////////////////////////////////////////////////////////////////////////// | 199 //////////////////////////////////////////////////////////////////////////////// |
| 253 // Drawing and utility functions | 200 // Drawing and utility functions |
| 254 | 201 |
| 255 // Returns the width of the tab endcap at scale 1. More precisely, this is the | 202 // Returns the width of the tab endcap at scale 1. More precisely, this is the |
| 256 // width of the curve making up either the outer or inner edge of the stroke; | 203 // width of the curve making up either the outer or inner edge of the stroke; |
| 257 // since these two curves are horizontally offset by 1 px (regardless of scale), | 204 // since these two curves are horizontally offset by 1 px (regardless of scale), |
| 258 // the total width of the endcap from tab outer edge to the inside end of the | 205 // the total width of the endcap from tab outer edge to the inside end of the |
| 259 // stroke inner edge is (GetUnscaledEndcapWidth() * scale) + 1. | 206 // stroke inner edge is (GetUnscaledEndcapWidth() * scale) + 1. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 | 268 |
| 322 // Returns a path corresponding to the tab's outer border for a given tab |size| | 269 // Returns a path corresponding to the tab's outer border for a given tab |size| |
| 323 // and |scale|. If |unscale_at_end| is true, this path will be normalized to a | 270 // and |scale|. If |unscale_at_end| is true, this path will be normalized to a |
| 324 // 1x scale by scaling by 1/scale before returning. If |extend_to_top| is true, | 271 // 1x scale by scaling by 1/scale before returning. If |extend_to_top| is true, |
| 325 // the path is extended vertically to the top of the tab bounds. The caller | 272 // the path is extended vertically to the top of the tab bounds. The caller |
| 326 // uses this for Fitts' Law purposes in maximized/fullscreen mode. | 273 // uses this for Fitts' Law purposes in maximized/fullscreen mode. |
| 327 gfx::Path GetBorderPath(float scale, | 274 gfx::Path GetBorderPath(float scale, |
| 328 bool unscale_at_end, | 275 bool unscale_at_end, |
| 329 bool extend_to_top, | 276 bool extend_to_top, |
| 330 const gfx::Size& size) { | 277 const gfx::Size& size) { |
| 278 const float top = scale - 1; | |
| 279 const float right = size.width() * scale; | |
| 280 const float bottom = size.height() * scale; | |
| 281 const float unscaled_endcap_width = GetUnscaledEndcapWidth(); | |
| 282 | |
| 331 gfx::Path path; | 283 gfx::Path path; |
| 332 if (ui::MaterialDesignController::IsModeMaterial()) { | 284 path.moveTo(0, bottom); |
| 333 const float top = scale - 1; | 285 path.rLineTo(0, -1); |
| 334 const float right = size.width() * scale; | 286 path.rCubicTo(0.75 * scale, 0, 1.625 * scale, -0.5 * scale, 2 * scale, |
| 335 const float bottom = size.height() * scale; | 287 -1.5 * scale); |
| 336 const float unscaled_endcap_width = GetUnscaledEndcapWidth(); | 288 path.lineTo((unscaled_endcap_width - 2) * scale, top + 1.5 * scale); |
| 289 if (extend_to_top) { | |
| 290 // Create the vertical extension by extending the side diagonals until | |
| 291 // they reach the top of the bounds. | |
| 292 const float dy = 2.5 * scale - 1; | |
| 293 const float dx = Tab::GetInverseDiagonalSlope() * dy; | |
| 294 path.rLineTo(dx, -dy); | |
| 295 path.lineTo(right - (unscaled_endcap_width - 2) * scale - dx, 0); | |
| 296 path.rLineTo(dx, dy); | |
| 297 } else { | |
| 298 path.rCubicTo(0.375 * scale, -scale, 1.25 * scale, -1.5 * scale, 2 * scale, | |
| 299 -1.5 * scale); | |
| 300 path.lineTo(right - unscaled_endcap_width * scale, top); | |
| 301 path.rCubicTo(0.75 * scale, 0, 1.625 * scale, 0.5 * scale, 2 * scale, | |
| 302 1.5 * scale); | |
| 303 } | |
| 304 path.lineTo(right - 2 * scale, bottom - 1 - 1.5 * scale); | |
| 305 path.rCubicTo(0.375 * scale, scale, 1.25 * scale, 1.5 * scale, 2 * scale, | |
| 306 1.5 * scale); | |
| 307 path.rLineTo(0, 1); | |
| 308 path.close(); | |
| 337 | 309 |
| 338 path.moveTo(0, bottom); | 310 if (unscale_at_end && (scale != 1)) |
| 339 path.rLineTo(0, -1); | 311 path.transform(SkMatrix::MakeScale(1.f / scale)); |
| 340 path.rCubicTo(0.75 * scale, 0, 1.625 * scale, -0.5 * scale, 2 * scale, | |
| 341 -1.5 * scale); | |
| 342 path.lineTo((unscaled_endcap_width - 2) * scale, top + 1.5 * scale); | |
| 343 if (extend_to_top) { | |
| 344 // Create the vertical extension by extending the side diagonals until | |
| 345 // they reach the top of the bounds. | |
| 346 const float dy = 2.5 * scale - 1; | |
| 347 const float dx = Tab::GetInverseDiagonalSlope() * dy; | |
| 348 path.rLineTo(dx, -dy); | |
| 349 path.lineTo(right - (unscaled_endcap_width - 2) * scale - dx, 0); | |
| 350 path.rLineTo(dx, dy); | |
| 351 } else { | |
| 352 path.rCubicTo(0.375 * scale, -scale, 1.25 * scale, -1.5 * scale, | |
| 353 2 * scale, -1.5 * scale); | |
| 354 path.lineTo(right - unscaled_endcap_width * scale, top); | |
| 355 path.rCubicTo(0.75 * scale, 0, 1.625 * scale, 0.5 * scale, 2 * scale, | |
| 356 1.5 * scale); | |
| 357 } | |
| 358 path.lineTo(right - 2 * scale, bottom - 1 - 1.5 * scale); | |
| 359 path.rCubicTo(0.375 * scale, scale, 1.25 * scale, 1.5 * scale, 2 * scale, | |
| 360 1.5 * scale); | |
| 361 path.rLineTo(0, 1); | |
| 362 path.close(); | |
| 363 | |
| 364 if (unscale_at_end && (scale != 1)) | |
| 365 path.transform(SkMatrix::MakeScale(1.f / scale)); | |
| 366 } else { | |
| 367 // Hit mask constants. | |
| 368 const SkScalar kTabCapWidth = 15; | |
| 369 const SkScalar kTabTopCurveWidth = 4; | |
| 370 const SkScalar kTabBottomCurveWidth = 3; | |
| 371 #if defined(OS_MACOSX) | |
| 372 // Mac's Cocoa UI doesn't have shadows. | |
| 373 const SkScalar kTabInset = 0; | |
| 374 #elif defined(TOOLKIT_VIEWS) | |
| 375 // The views browser UI has shadows in the left, right and top parts of the | |
| 376 // tab. | |
| 377 const SkScalar kTabInset = 6; | |
| 378 #endif | |
| 379 | |
| 380 SkScalar left = kTabInset; | |
| 381 SkScalar top = SkIntToScalar(0); | |
| 382 SkScalar right = SkIntToScalar(size.width()) - kTabInset; | |
| 383 SkScalar bottom = SkIntToScalar(size.height()); | |
| 384 | |
| 385 // Start in the lower-left corner. | |
| 386 path.moveTo(left, bottom); | |
| 387 | |
| 388 // Left end cap. | |
| 389 path.lineTo(left + kTabBottomCurveWidth, bottom - kTabBottomCurveWidth); | |
| 390 path.lineTo(left + kTabCapWidth - kTabTopCurveWidth, | |
| 391 top + kTabTopCurveWidth); | |
| 392 path.lineTo(left + kTabCapWidth, top); | |
| 393 | |
| 394 // Connect to the right cap. | |
| 395 path.lineTo(right - kTabCapWidth, top); | |
| 396 | |
| 397 // Right end cap. | |
| 398 path.lineTo(right - kTabCapWidth + kTabTopCurveWidth, | |
| 399 top + kTabTopCurveWidth); | |
| 400 path.lineTo(right - kTabBottomCurveWidth, bottom - kTabBottomCurveWidth); | |
| 401 path.lineTo(right, bottom); | |
| 402 | |
| 403 // Close out the path. | |
| 404 path.lineTo(left, bottom); | |
| 405 path.close(); | |
| 406 | |
| 407 // Unscaling is not necessary since we never scaled up to begin with. | |
| 408 } | |
| 409 | 312 |
| 410 return path; | 313 return path; |
| 411 } | 314 } |
| 412 | 315 |
| 413 void PaintTabFill(gfx::Canvas* canvas, | |
| 414 const gfx::ImageSkia& fill_image, | |
| 415 gfx::Rect rect, | |
| 416 bool is_active) { | |
| 417 const gfx::Insets tab_insets(GetLayoutInsets(TAB)); | |
| 418 // If this isn't the foreground tab, don't draw over the toolbar, but do | |
| 419 // include the 1 px divider stroke at the bottom. | |
| 420 const int toolbar_overlap = is_active ? 0 : (tab_insets.bottom() - 1); | |
| 421 | |
| 422 // Draw left edge. | |
| 423 gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( | |
| 424 fill_image, rect.x(), rect.y(), g_mask_images.l_width, rect.height()); | |
| 425 gfx::ImageSkia theme_l = gfx::ImageSkiaOperations::CreateMaskedImage( | |
| 426 tab_l, *g_mask_images.image_l); | |
| 427 canvas->DrawImageInt( | |
| 428 theme_l, 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, 0, 0, | |
| 429 theme_l.width(), theme_l.height() - toolbar_overlap, false); | |
| 430 | |
| 431 // Draw right edge. | |
| 432 gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( | |
| 433 fill_image, rect.right() - g_mask_images.r_width, rect.y(), | |
| 434 g_mask_images.r_width, rect.height()); | |
| 435 gfx::ImageSkia theme_r = gfx::ImageSkiaOperations::CreateMaskedImage( | |
| 436 tab_r, *g_mask_images.image_r); | |
| 437 canvas->DrawImageInt(theme_r, 0, 0, theme_r.width(), | |
| 438 theme_r.height() - toolbar_overlap, | |
| 439 rect.width() - theme_r.width(), 0, theme_r.width(), | |
| 440 theme_r.height() - toolbar_overlap, false); | |
| 441 | |
| 442 // Draw center. Instead of masking out the top portion we simply skip over it | |
| 443 // by incrementing by the top padding, since it's a simple rectangle. | |
| 444 rect.Inset(g_mask_images.l_width, tab_insets.top(), g_mask_images.r_width, | |
| 445 toolbar_overlap); | |
| 446 canvas->TileImageInt(fill_image, rect.x(), rect.y(), g_mask_images.l_width, | |
| 447 tab_insets.top(), rect.width(), rect.height()); | |
| 448 } | |
| 449 | |
| 450 } // namespace | 316 } // namespace |
| 451 | 317 |
| 452 //////////////////////////////////////////////////////////////////////////////// | 318 //////////////////////////////////////////////////////////////////////////////// |
| 453 // FaviconCrashAnimation | 319 // FaviconCrashAnimation |
| 454 // | 320 // |
| 455 // A custom animation subclass to manage the favicon crash animation. | 321 // A custom animation subclass to manage the favicon crash animation. |
| 456 class Tab::FaviconCrashAnimation : public gfx::LinearAnimation, | 322 class Tab::FaviconCrashAnimation : public gfx::LinearAnimation, |
| 457 public gfx::AnimationDelegate { | 323 public gfx::AnimationDelegate { |
| 458 public: | 324 public: |
| 459 explicit FaviconCrashAnimation(Tab* target) | 325 explicit FaviconCrashAnimation(Tab* target) |
| (...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1067 } | 933 } |
| 1068 // The Label will automatically center the font's cap height within the | 934 // The Label will automatically center the font's cap height within the |
| 1069 // provided vertical space. | 935 // provided vertical space. |
| 1070 title_->SetBoundsRect( | 936 title_->SetBoundsRect( |
| 1071 gfx::Rect(title_left, lb.y(), std::max(title_width, 0), lb.height())); | 937 gfx::Rect(title_left, lb.y(), std::max(title_width, 0), lb.height())); |
| 1072 } | 938 } |
| 1073 title_->SetVisible(show_title); | 939 title_->SetVisible(show_title); |
| 1074 } | 940 } |
| 1075 | 941 |
| 1076 void Tab::OnThemeChanged() { | 942 void Tab::OnThemeChanged() { |
| 1077 LoadTabImages(); | |
| 1078 OnButtonColorMaybeChanged(); | 943 OnButtonColorMaybeChanged(); |
| 1079 favicon_ = gfx::ImageSkia(); | 944 favicon_ = gfx::ImageSkia(); |
| 1080 } | 945 } |
| 1081 | 946 |
| 1082 const char* Tab::GetClassName() const { | 947 const char* Tab::GetClassName() const { |
| 1083 return kViewClassName; | 948 return kViewClassName; |
| 1084 } | 949 } |
| 1085 | 950 |
| 1086 bool Tab::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { | 951 bool Tab::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { |
| 1087 // Note: Anything that affects the tooltip text should be accounted for when | 952 // Note: Anything that affects the tooltip text should be accounted for when |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1364 if (has_custom_image || hover_controller_.ShouldDraw()) { | 1229 if (has_custom_image || hover_controller_.ShouldDraw()) { |
| 1365 PaintTabBackgroundUsingFillId(canvas, canvas, false, fill_id, | 1230 PaintTabBackgroundUsingFillId(canvas, canvas, false, fill_id, |
| 1366 has_custom_image, y_offset); | 1231 has_custom_image, y_offset); |
| 1367 return; | 1232 return; |
| 1368 } | 1233 } |
| 1369 | 1234 |
| 1370 // For efficiency, we don't use separate fill and stroke images unless we | 1235 // For efficiency, we don't use separate fill and stroke images unless we |
| 1371 // really need to clip the stroke and not the fill (for stacked tabs). This | 1236 // really need to clip the stroke and not the fill (for stacked tabs). This |
| 1372 // saves memory and avoids an extra image draw at the cost of recalculating | 1237 // saves memory and avoids an extra image draw at the cost of recalculating |
| 1373 // the images when MaySetClip() toggles. | 1238 // the images when MaySetClip() toggles. |
| 1374 const bool use_fill_and_stroke_images = | 1239 const bool use_fill_and_stroke_images = controller_->MaySetClip(); |
| 1375 controller_->MaySetClip() && | |
| 1376 ui::MaterialDesignController::IsModeMaterial(); | |
| 1377 | 1240 |
| 1378 const ImageCacheEntryMetadata metadata( | 1241 const ImageCacheEntryMetadata metadata( |
| 1379 fill_id, tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB), | 1242 tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB), |
| 1380 controller_->GetToolbarTopSeparatorColor(), use_fill_and_stroke_images, | 1243 controller_->GetToolbarTopSeparatorColor(), use_fill_and_stroke_images, |
| 1381 canvas->image_scale(), size()); | 1244 canvas->image_scale(), size()); |
| 1382 auto it = std::find_if( | 1245 auto it = std::find_if( |
| 1383 g_image_cache->begin(), g_image_cache->end(), | 1246 g_image_cache->begin(), g_image_cache->end(), |
| 1384 [&metadata](const ImageCacheEntry& e) { return e.metadata == metadata; }); | 1247 [&metadata](const ImageCacheEntry& e) { return e.metadata == metadata; }); |
| 1385 if (it == g_image_cache->end()) { | 1248 if (it == g_image_cache->end()) { |
| 1386 gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false); | 1249 gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false); |
| 1387 if (use_fill_and_stroke_images) { | 1250 if (use_fill_and_stroke_images) { |
| 1388 gfx::Canvas tmp_fill_canvas(size(), canvas->image_scale(), false); | 1251 gfx::Canvas tmp_fill_canvas(size(), canvas->image_scale(), false); |
| 1389 PaintTabBackgroundUsingFillId(&tmp_fill_canvas, &tmp_canvas, false, | 1252 PaintTabBackgroundUsingFillId(&tmp_fill_canvas, &tmp_canvas, false, |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1411 } | 1274 } |
| 1412 canvas->DrawImageInt(it->stroke_image, 0, 0); | 1275 canvas->DrawImageInt(it->stroke_image, 0, 0); |
| 1413 } | 1276 } |
| 1414 | 1277 |
| 1415 void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* fill_canvas, | 1278 void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* fill_canvas, |
| 1416 gfx::Canvas* stroke_canvas, | 1279 gfx::Canvas* stroke_canvas, |
| 1417 bool is_active, | 1280 bool is_active, |
| 1418 int fill_id, | 1281 int fill_id, |
| 1419 bool has_custom_image, | 1282 bool has_custom_image, |
| 1420 int y_offset) { | 1283 int y_offset) { |
| 1421 const ui::ThemeProvider* tp = GetThemeProvider(); | 1284 gfx::Path fill; |
| 1422 const SkColor toolbar_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR); | 1285 SkPaint paint; |
| 1423 gfx::ImageSkia* fill_image = tp->GetImageSkiaNamed(fill_id); | 1286 paint.setAntiAlias(true); |
| 1424 // The tab image needs to be lined up with the background image | |
| 1425 // so that it feels partially transparent. These offsets represent the tab | |
| 1426 // position within the frame background image. | |
| 1427 const int x_offset = GetMirroredX() + background_offset_.x(); | |
| 1428 | 1287 |
| 1429 const SkScalar kMinHoverRadius = 16; | 1288 // Draw the fill. |
| 1430 const SkScalar radius = | 1289 { |
| 1431 std::max(SkFloatToScalar(width() / 4.f), kMinHoverRadius); | 1290 gfx::ScopedCanvas scoped_canvas(fill_canvas); |
| 1432 const bool draw_hover = !is_active && hover_controller_.ShouldDraw(); | 1291 const float scale = fill_canvas->UndoDeviceScaleFactor(); |
| 1433 SkPoint hover_location(gfx::PointToSkPoint(hover_controller_.location())); | 1292 const ui::ThemeProvider* tp = GetThemeProvider(); |
| 1434 const SkColor hover_color = | 1293 const SkColor toolbar_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR); |
| 1435 SkColorSetA(toolbar_color, hover_controller_.GetAlpha()); | |
| 1436 | 1294 |
| 1437 if (ui::MaterialDesignController::IsModeMaterial()) { | 1295 fill = GetFillPath(scale, size()); |
| 1438 gfx::Path fill; | 1296 { |
| 1439 SkPaint paint; | 1297 gfx::ScopedCanvas clip_scoper(fill_canvas); |
| 1440 paint.setAntiAlias(true); | 1298 fill_canvas->ClipPath(fill, true); |
| 1299 if (has_custom_image) { | |
| 1300 gfx::ScopedCanvas scale_scoper(fill_canvas); | |
| 1301 fill_canvas->sk_canvas()->scale(scale, scale); | |
| 1302 fill_canvas->TileImageInt(*tp->GetImageSkiaNamed(fill_id), | |
| 1303 GetMirroredX() + background_offset_.x(), | |
| 1304 y_offset, 0, 0, width(), height()); | |
| 1305 } else { | |
| 1306 paint.setColor( | |
| 1307 is_active ? toolbar_color | |
| 1308 : tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB)); | |
| 1309 fill_canvas->DrawRect( | |
| 1310 gfx::ScaleToEnclosingRect(GetLocalBounds(), scale), paint); | |
| 1311 } | |
| 1441 | 1312 |
| 1442 // Draw the fill. | 1313 if (!is_active && hover_controller_.ShouldDraw()) { |
| 1443 { | 1314 SkPoint hover_location( |
| 1444 gfx::ScopedCanvas scoped_canvas(fill_canvas); | 1315 gfx::PointToSkPoint(hover_controller_.location())); |
| 1445 const float scale = fill_canvas->UndoDeviceScaleFactor(); | 1316 hover_location.scale(SkFloatToScalar(scale)); |
| 1446 | 1317 const SkScalar kMinHoverRadius = 16; |
| 1447 fill = GetFillPath(scale, size()); | 1318 const SkScalar radius = |
| 1448 { | 1319 std::max(SkFloatToScalar(width() / 4.f), kMinHoverRadius); |
| 1449 gfx::ScopedCanvas clip_scoper(fill_canvas); | 1320 DrawHighlight(fill_canvas, hover_location, radius * scale, |
| 1450 fill_canvas->ClipPath(fill, true); | 1321 SkColorSetA(toolbar_color, hover_controller_.GetAlpha())); |
| 1451 if (has_custom_image) { | |
| 1452 gfx::ScopedCanvas scale_scoper(fill_canvas); | |
| 1453 fill_canvas->sk_canvas()->scale(scale, scale); | |
| 1454 fill_canvas->TileImageInt(*fill_image, x_offset, y_offset, 0, 0, | |
| 1455 width(), height()); | |
| 1456 } else { | |
| 1457 paint.setColor( | |
| 1458 is_active ? toolbar_color | |
| 1459 : tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB)); | |
| 1460 fill_canvas->DrawRect( | |
| 1461 gfx::ScaleToEnclosingRect(GetLocalBounds(), scale), paint); | |
| 1462 } | |
| 1463 if (draw_hover) { | |
| 1464 hover_location.scale(SkFloatToScalar(scale)); | |
| 1465 DrawHighlight(fill_canvas, hover_location, radius * scale, | |
| 1466 hover_color); | |
| 1467 } | |
| 1468 } | 1322 } |
| 1469 } | 1323 } |
| 1324 } | |
| 1470 | 1325 |
| 1471 // Draw the stroke. | 1326 // Draw the stroke. |
| 1472 { | 1327 { |
| 1473 gfx::ScopedCanvas scoped_canvas(stroke_canvas); | 1328 gfx::ScopedCanvas scoped_canvas(stroke_canvas); |
| 1474 const float scale = stroke_canvas->UndoDeviceScaleFactor(); | 1329 const float scale = stroke_canvas->UndoDeviceScaleFactor(); |
| 1475 | 1330 |
| 1476 gfx::Path stroke = GetBorderPath(scale, false, false, size()); | 1331 gfx::Path stroke = GetBorderPath(scale, false, false, size()); |
| 1477 Op(stroke, fill, kDifference_SkPathOp, &stroke); | 1332 Op(stroke, fill, kDifference_SkPathOp, &stroke); |
| 1478 if (!is_active) { | 1333 if (!is_active) { |
| 1479 // Clip out the bottom line; this will be drawn for us by | 1334 // Clip out the bottom line; this will be drawn for us by |
| 1480 // TabStrip::PaintChildren(). | 1335 // TabStrip::PaintChildren(). |
| 1481 stroke_canvas->ClipRect( | 1336 stroke_canvas->ClipRect( |
| 1482 gfx::RectF(width() * scale, height() * scale - 1)); | 1337 gfx::RectF(width() * scale, height() * scale - 1)); |
| 1483 } | |
| 1484 paint.setColor(controller_->GetToolbarTopSeparatorColor()); | |
| 1485 stroke_canvas->DrawPath(stroke, paint); | |
| 1486 } | 1338 } |
| 1487 } else { | 1339 paint.setColor(controller_->GetToolbarTopSeparatorColor()); |
| 1488 gfx::Canvas* canvas = stroke_canvas; | 1340 stroke_canvas->DrawPath(stroke, paint); |
| 1489 gfx::Rect rect(gfx::Point(x_offset, y_offset), size()); | |
| 1490 if (draw_hover) { | |
| 1491 // Draw everything to a temporary canvas so we can extract an image for | |
| 1492 // use in masking the hover glow. | |
| 1493 gfx::Canvas background_canvas(size(), canvas->image_scale(), false); | |
| 1494 PaintTabFill(&background_canvas, *fill_image, rect, is_active); | |
| 1495 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); | |
| 1496 canvas->DrawImageInt(background_image, 0, 0); | |
| 1497 | |
| 1498 gfx::Canvas hover_canvas(size(), canvas->image_scale(), false); | |
| 1499 DrawHighlight(&hover_canvas, hover_location, radius, hover_color); | |
| 1500 gfx::ImageSkia result = gfx::ImageSkiaOperations::CreateMaskedImage( | |
| 1501 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); | |
| 1502 canvas->DrawImageInt(result, 0, 0); | |
| 1503 } else { | |
| 1504 PaintTabFill(canvas, *fill_image, rect, is_active); | |
| 1505 } | |
| 1506 | |
| 1507 // Now draw the stroke, highlights, and shadows around the tab edge. | |
| 1508 TabImages* stroke_images = | |
| 1509 is_active ? &g_active_images : &g_inactive_images; | |
| 1510 canvas->DrawImageInt(*stroke_images->image_l, 0, 0); | |
| 1511 canvas->TileImageInt( | |
| 1512 *stroke_images->image_c, stroke_images->l_width, 0, | |
| 1513 width() - stroke_images->l_width - stroke_images->r_width, height()); | |
| 1514 canvas->DrawImageInt(*stroke_images->image_r, | |
| 1515 width() - stroke_images->r_width, 0); | |
| 1516 } | 1341 } |
| 1517 } | 1342 } |
| 1518 | 1343 |
| 1519 void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( | 1344 void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( |
| 1520 gfx::Canvas* canvas, | 1345 gfx::Canvas* canvas, |
| 1521 const gfx::Rect& favicon_draw_bounds) { | 1346 const gfx::Rect& favicon_draw_bounds) { |
| 1522 // The pinned tab title changed indicator consists of two parts: | 1347 // The pinned tab title changed indicator consists of two parts: |
| 1523 // . a clear (totally transparent) part over the bottom right (or left in rtl) | 1348 // . a clear (totally transparent) part over the bottom right (or left in rtl) |
| 1524 // of the favicon. This is done by drawing the favicon to a canvas, then | 1349 // of the favicon. This is done by drawing the favicon to a canvas, then |
| 1525 // drawing the clear part on top of the favicon. | 1350 // drawing the clear part on top of the favicon. |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1747 | 1572 |
| 1748 // Extends the area to the bottom when the crash animation is in progress. | 1573 // Extends the area to the bottom when the crash animation is in progress. |
| 1749 if (crash_icon_animation_->is_animating()) | 1574 if (crash_icon_animation_->is_animating()) |
| 1750 bounds.set_height(height() - bounds.y()); | 1575 bounds.set_height(height() - bounds.y()); |
| 1751 bounds.set_x(GetMirroredXForRect(bounds)); | 1576 bounds.set_x(GetMirroredXForRect(bounds)); |
| 1752 SchedulePaintInRect(bounds); | 1577 SchedulePaintInRect(bounds); |
| 1753 } | 1578 } |
| 1754 | 1579 |
| 1755 gfx::Rect Tab::GetImmersiveBarRect() const { | 1580 gfx::Rect Tab::GetImmersiveBarRect() const { |
| 1756 // The main bar is as wide as the normal tab's horizontal top line. | 1581 // The main bar is as wide as the normal tab's horizontal top line. |
| 1757 // This top line of the tab extends a few pixels left and right of the | 1582 gfx::Rect contents = GetContentsBounds(); |
|
Peter Kasting
2016/09/26 21:05:29
This seems to be a behavior change? The old code,
Evan Stade
2016/09/26 21:57:34
I don't think so --- the tab's border is set here:
Peter Kasting
2016/09/26 22:02:41
Oh, I was thinking GetLocalBounds(), not GetConten
| |
| 1758 // center image due to pixels in the rounded corner images. | 1583 contents.set_y(0); |
| 1759 const int kBarPadding = 1; | 1584 contents.set_height(kImmersiveBarHeight); |
| 1760 int main_bar_left = g_active_images.l_width - kBarPadding; | 1585 return contents; |
| 1761 int main_bar_right = width() - g_active_images.r_width + kBarPadding; | |
| 1762 return gfx::Rect( | |
| 1763 main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight); | |
| 1764 } | 1586 } |
| OLD | NEW |