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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 | 109 |
| 110 // The minimum opacity (out of 1) when a tab (either active or inactive) is | 110 // The minimum opacity (out of 1) when a tab (either active or inactive) is |
| 111 // throbbing in the immersive mode light strip. | 111 // throbbing in the immersive mode light strip. |
| 112 const double kImmersiveTabMinThrobOpacity = 0.66; | 112 const double kImmersiveTabMinThrobOpacity = 0.66; |
| 113 | 113 |
| 114 // Number of steps in the immersive mode loading animation. | 114 // Number of steps in the immersive mode loading animation. |
| 115 const int kImmersiveLoadingStepCount = 32; | 115 const int kImmersiveLoadingStepCount = 32; |
| 116 | 116 |
| 117 const char kTabCloseButtonName[] = "TabCloseButton"; | 117 const char kTabCloseButtonName[] = "TabCloseButton"; |
| 118 | 118 |
| 119 //////////////////////////////////////////////////////////////////////////////// | |
| 120 // ImageCacheEntryMetadata | |
| 121 // | |
| 122 // All metadata necessary to uniquely identify a cached image. | |
| 123 struct ImageCacheEntryMetadata { | |
| 124 ImageCacheEntryMetadata(int resource_id, | |
| 125 SkColor fill_color, | |
| 126 SkColor stroke_color, | |
| 127 ui::ScaleFactor scale_factor, | |
| 128 const gfx::Size& size); | |
| 129 | |
| 130 ~ImageCacheEntryMetadata(); | |
| 131 | |
| 132 bool operator==(const ImageCacheEntryMetadata& rhs) const; | |
| 133 | |
| 134 int resource_id; // Only needed by pre-MD | |
| 135 SkColor fill_color; // Both colors only needed by MD | |
| 136 SkColor stroke_color; | |
| 137 ui::ScaleFactor scale_factor; | |
| 138 gfx::Size size; | |
| 139 }; | |
| 140 | |
| 141 ImageCacheEntryMetadata::ImageCacheEntryMetadata(int resource_id, | |
| 142 SkColor fill_color, | |
| 143 SkColor stroke_color, | |
| 144 ui::ScaleFactor scale_factor, | |
| 145 const gfx::Size& size) | |
| 146 : resource_id(resource_id), | |
| 147 fill_color(fill_color), | |
| 148 stroke_color(stroke_color), | |
| 149 scale_factor(scale_factor), | |
| 150 size(size) { | |
| 151 DCHECK_NE(ui::SCALE_FACTOR_NONE, scale_factor); | |
| 152 | |
| 153 // Some fields are only relevant for pre-MD vs. MD. Erase the irrelevant ones | |
| 154 // so they don't cause incorrect cache misses. | |
| 155 // TODO(pkasting): Remove |resource_id| field when non-MD code is deleted. | |
| 156 if (ui::MaterialDesignController::IsModeMaterial()) | |
| 157 resource_id = 0; | |
| 158 else | |
| 159 fill_color = stroke_color = SK_ColorTRANSPARENT; | |
| 160 } | |
| 161 | |
| 162 ImageCacheEntryMetadata::~ImageCacheEntryMetadata() {} | |
| 163 | |
| 164 bool ImageCacheEntryMetadata::operator==( | |
| 165 const ImageCacheEntryMetadata& rhs) const { | |
| 166 return resource_id == rhs.resource_id && fill_color == rhs.fill_color && | |
| 167 stroke_color == rhs.stroke_color && scale_factor == rhs.scale_factor && | |
| 168 size == rhs.size; | |
| 169 } | |
| 170 | |
| 171 //////////////////////////////////////////////////////////////////////////////// | |
| 172 // ImageCacheEntry and cache management | |
| 173 // | |
| 174 // A cached image and the metadata used to generate it. | |
| 175 struct ImageCacheEntry { | |
| 176 ImageCacheEntry(const ImageCacheEntryMetadata& metadata, | |
| 177 const gfx::ImageSkia& image); | |
| 178 ~ImageCacheEntry(); | |
| 179 | |
| 180 ImageCacheEntryMetadata metadata; | |
| 181 gfx::ImageSkia image; | |
| 182 }; | |
| 183 | |
| 184 ImageCacheEntry::ImageCacheEntry(const ImageCacheEntryMetadata& metadata, | |
| 185 const gfx::ImageSkia& image) | |
| 186 : metadata(metadata), image(image) {} | |
| 187 | |
| 188 ImageCacheEntry::~ImageCacheEntry() {} | |
| 189 | |
| 190 typedef std::list<ImageCacheEntry> ImageCache; | |
| 191 | |
| 192 // As the majority of the tabs are inactive, and painting tabs is slowish, | |
| 193 // we cache a handful of the inactive tab backgrounds here. | |
| 194 static ImageCache* image_cache = NULL; | |
|
Greg Levin
2016/07/14 18:26:45
Is there a preferred naming convention for static
msw
2016/07/14 20:14:49
I think 'g' is commonly used as a prefix for file-
| |
| 195 | |
| 196 struct TabImages { | |
| 197 gfx::ImageSkia* image_l; | |
| 198 gfx::ImageSkia* image_c; | |
| 199 gfx::ImageSkia* image_r; | |
| 200 int l_width; | |
| 201 int r_width; | |
| 202 }; | |
| 203 static TabImages active_images = {0}; | |
| 204 static TabImages inactive_images = {0}; | |
| 205 static TabImages mask_images = {0}; | |
| 206 | |
| 207 // Loads the images to be used for the tab background. | |
| 208 void LoadTabImages() { | |
| 209 image_cache->clear(); | |
| 210 | |
| 211 // We're not letting people override tab images just yet. | |
| 212 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 213 | |
| 214 active_images.image_l = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_LEFT); | |
| 215 active_images.image_c = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_CENTER); | |
| 216 active_images.image_r = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_RIGHT); | |
| 217 active_images.l_width = active_images.image_l->width(); | |
| 218 active_images.r_width = active_images.image_r->width(); | |
| 219 | |
| 220 inactive_images.image_l = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_LEFT); | |
| 221 inactive_images.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); | |
| 222 inactive_images.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); | |
| 223 inactive_images.l_width = inactive_images.image_l->width(); | |
| 224 inactive_images.r_width = inactive_images.image_r->width(); | |
| 225 | |
| 226 mask_images.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); | |
| 227 mask_images.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); | |
| 228 mask_images.l_width = mask_images.image_l->width(); | |
| 229 mask_images.r_width = mask_images.image_r->width(); | |
| 230 } | |
| 231 | |
| 232 // Performs a one-time initialization of static resources such as tab images. | |
| 233 void InitTabResources() { | |
| 234 static bool initialized = false; | |
| 235 if (initialized) | |
| 236 return; | |
| 237 | |
| 238 initialized = true; | |
| 239 image_cache = new ImageCache(); | |
| 240 | |
| 241 // Load the tab images once now, and maybe again later if the theme changes. | |
| 242 LoadTabImages(); | |
| 243 } | |
| 244 | |
| 245 //////////////////////////////////////////////////////////////////////////////// | |
| 246 // Drawing and utility functions | |
| 247 | |
| 119 // Returns the width of the tab endcap at scale 1. More precisely, this is the | 248 // Returns the width of the tab endcap at scale 1. More precisely, this is the |
| 120 // width of the curve making up either the outer or inner edge of the stroke; | 249 // width of the curve making up either the outer or inner edge of the stroke; |
| 121 // since these two curves are horizontally offset by 1 px (regardless of scale), | 250 // since these two curves are horizontally offset by 1 px (regardless of scale), |
| 122 // the total width of the endcap from tab outer edge to the inside end of the | 251 // the total width of the endcap from tab outer edge to the inside end of the |
| 123 // stroke inner edge is (GetUnscaledEndcapWidth() * scale) + 1. | 252 // stroke inner edge is (GetUnscaledEndcapWidth() * scale) + 1. |
| 124 float GetUnscaledEndcapWidth() { | 253 float GetUnscaledEndcapWidth() { |
| 125 return GetLayoutInsets(TAB).left() - 0.5f; | 254 return GetLayoutInsets(TAB).left() - 0.5f; |
| 126 } | 255 } |
| 127 | 256 |
| 128 void DrawHighlight(gfx::Canvas* canvas, | 257 void DrawHighlight(gfx::Canvas* canvas, |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 140 } | 269 } |
| 141 | 270 |
| 142 // Returns whether the favicon for the given URL should be colored according to | 271 // Returns whether the favicon for the given URL should be colored according to |
| 143 // the browser theme. | 272 // the browser theme. |
| 144 bool ShouldThemifyFaviconForUrl(const GURL& url) { | 273 bool ShouldThemifyFaviconForUrl(const GURL& url) { |
| 145 return url.SchemeIs(content::kChromeUIScheme) && | 274 return url.SchemeIs(content::kChromeUIScheme) && |
| 146 url.host() != chrome::kChromeUIHelpHost && | 275 url.host() != chrome::kChromeUIHelpHost && |
| 147 url.host() != chrome::kChromeUIUberHost; | 276 url.host() != chrome::kChromeUIUberHost; |
| 148 } | 277 } |
| 149 | 278 |
| 279 // Computes a path corresponding to the tab's content region inside the outer | |
| 280 // stroke. | |
|
Greg Levin
2016/07/14 18:26:45
These three functions were *almost* static (just n
msw
2016/07/14 20:14:49
Acknowledged.
| |
| 281 void GetFillPath(float scale, const gfx::Size& size, SkPath* fill) { | |
| 282 const float right = size.width() * scale; | |
| 283 // The bottom of the tab needs to be pixel-aligned or else when we call | |
| 284 // ClipPath with anti-aliasing enabled it can cause artifacts. | |
| 285 const float bottom = std::ceil(size.height() * scale); | |
| 286 const float unscaled_endcap_width = GetUnscaledEndcapWidth(); | |
| 287 | |
| 288 fill->moveTo(right - 1, bottom); | |
| 289 fill->rCubicTo(-0.75 * scale, 0, -1.625 * scale, -0.5 * scale, -2 * scale, | |
| 290 -1.5 * scale); | |
| 291 fill->lineTo(right - 1 - (unscaled_endcap_width - 2) * scale, 2.5 * scale); | |
| 292 // Prevent overdraw in the center near minimum width (only happens if | |
| 293 // scale < 2). We could instead avoid this by increasing the tab inset | |
| 294 // values, but that would shift all the content inward as well, unless we | |
| 295 // then overlapped the content on the endcaps, by which point we'd have a | |
| 296 // huge mess. | |
| 297 const float scaled_endcap_width = 1 + unscaled_endcap_width * scale; | |
| 298 const float overlap = scaled_endcap_width * 2 - right; | |
| 299 const float offset = (overlap > 0) ? (overlap / 2) : 0; | |
| 300 fill->rCubicTo(-0.375 * scale, -1 * scale, -1.25 * scale + offset, | |
| 301 -1.5 * scale, -2 * scale + offset, -1.5 * scale); | |
| 302 if (overlap < 0) | |
| 303 fill->lineTo(scaled_endcap_width, scale); | |
| 304 fill->rCubicTo(-0.75 * scale, 0, -1.625 * scale - offset, 0.5 * scale, | |
| 305 -2 * scale - offset, 1.5 * scale); | |
| 306 fill->lineTo(1 + 2 * scale, bottom - 1.5 * scale); | |
| 307 fill->rCubicTo(-0.375 * scale, scale, -1.25 * scale, 1.5 * scale, -2 * scale, | |
| 308 1.5 * scale); | |
| 309 fill->close(); | |
| 310 } | |
| 311 | |
| 312 // Computes a path corresponding to the tab's outer border for a given |scale| | |
| 313 // and stores it in |path|. If |extend_to_top| is true, the path is extended | |
| 314 // vertically to the top of the tab bounds. The caller uses this for Fitts' | |
| 315 // Law purposes in maximized/fullscreen mode. | |
| 316 void GetBorderPath(float scale, | |
| 317 const gfx::Size& size, | |
| 318 bool extend_to_top, | |
| 319 SkPath* path) { | |
| 320 const float top = scale - 1; | |
| 321 const float right = size.width() * scale; | |
| 322 const float bottom = size.height() * scale; | |
| 323 const float unscaled_endcap_width = GetUnscaledEndcapWidth(); | |
| 324 | |
| 325 path->moveTo(0, bottom); | |
| 326 path->rLineTo(0, -1); | |
| 327 path->rCubicTo(0.75 * scale, 0, 1.625 * scale, -0.5 * scale, 2 * scale, | |
| 328 -1.5 * scale); | |
| 329 path->lineTo((unscaled_endcap_width - 2) * scale, top + 1.5 * scale); | |
| 330 if (extend_to_top) { | |
| 331 // Create the vertical extension by extending the side diagonals until they | |
| 332 // reach the top of the bounds. | |
| 333 const float dy = 2.5 * scale - 1; | |
| 334 const float dx = Tab::GetInverseDiagonalSlope() * dy; | |
| 335 path->rLineTo(dx, -dy); | |
| 336 path->lineTo(right - (unscaled_endcap_width - 2) * scale - dx, 0); | |
| 337 path->rLineTo(dx, dy); | |
| 338 } else { | |
| 339 path->rCubicTo(0.375 * scale, -scale, 1.25 * scale, -1.5 * scale, 2 * scale, | |
| 340 -1.5 * scale); | |
| 341 path->lineTo(right - unscaled_endcap_width * scale, top); | |
| 342 path->rCubicTo(0.75 * scale, 0, 1.625 * scale, 0.5 * scale, 2 * scale, | |
| 343 1.5 * scale); | |
| 344 } | |
| 345 path->lineTo(right - 2 * scale, bottom - 1 - 1.5 * scale); | |
| 346 path->rCubicTo(0.375 * scale, scale, 1.25 * scale, 1.5 * scale, 2 * scale, | |
| 347 1.5 * scale); | |
| 348 path->rLineTo(0, 1); | |
| 349 path->close(); | |
| 350 } | |
| 351 | |
| 352 void PaintTabFill(gfx::Canvas* canvas, | |
| 353 gfx::ImageSkia* fill_image, | |
| 354 int x_offset, | |
| 355 int y_offset, | |
| 356 const gfx::Size& size, | |
| 357 bool is_active) { | |
| 358 const gfx::Insets tab_insets(GetLayoutInsets(TAB)); | |
| 359 // If this isn't the foreground tab, don't draw over the toolbar, but do | |
| 360 // include the 1 px divider stroke at the bottom. | |
| 361 const int toolbar_overlap = is_active ? 0 : (tab_insets.bottom() - 1); | |
| 362 | |
| 363 // Draw left edge. | |
| 364 gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( | |
| 365 *fill_image, x_offset, y_offset, mask_images.l_width, size.height()); | |
| 366 gfx::ImageSkia theme_l = | |
| 367 gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *mask_images.image_l); | |
| 368 canvas->DrawImageInt( | |
| 369 theme_l, 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, 0, 0, | |
| 370 theme_l.width(), theme_l.height() - toolbar_overlap, false); | |
| 371 | |
| 372 // Draw right edge. | |
| 373 gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( | |
| 374 *fill_image, x_offset + size.width() - mask_images.r_width, y_offset, | |
| 375 mask_images.r_width, size.height()); | |
| 376 gfx::ImageSkia theme_r = | |
| 377 gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *mask_images.image_r); | |
| 378 canvas->DrawImageInt(theme_r, 0, 0, theme_r.width(), | |
| 379 theme_r.height() - toolbar_overlap, | |
| 380 size.width() - theme_r.width(), 0, theme_r.width(), | |
| 381 theme_r.height() - toolbar_overlap, false); | |
| 382 | |
| 383 // Draw center. Instead of masking out the top portion we simply skip over it | |
| 384 // by incrementing by the top padding, since it's a simple rectangle. | |
| 385 canvas->TileImageInt(*fill_image, x_offset + mask_images.l_width, | |
| 386 y_offset + tab_insets.top(), mask_images.l_width, | |
| 387 tab_insets.top(), | |
| 388 size.width() - mask_images.l_width - mask_images.r_width, | |
| 389 size.height() - tab_insets.top() - toolbar_overlap); | |
| 390 } | |
| 391 | |
| 150 } // namespace | 392 } // namespace |
| 151 | 393 |
| 152 //////////////////////////////////////////////////////////////////////////////// | 394 //////////////////////////////////////////////////////////////////////////////// |
| 153 // FaviconCrashAnimation | 395 // FaviconCrashAnimation |
| 154 // | 396 // |
| 155 // A custom animation subclass to manage the favicon crash animation. | 397 // A custom animation subclass to manage the favicon crash animation. |
| 156 class Tab::FaviconCrashAnimation : public gfx::LinearAnimation, | 398 class Tab::FaviconCrashAnimation : public gfx::LinearAnimation, |
| 157 public gfx::AnimationDelegate { | 399 public gfx::AnimationDelegate { |
| 158 public: | 400 public: |
| 159 explicit FaviconCrashAnimation(Tab* target) | 401 explicit FaviconCrashAnimation(Tab* target) |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 405 waiting_state_.color = | 647 waiting_state_.color = |
| 406 tp->GetColor(ThemeProperties::COLOR_TAB_THROBBER_WAITING); | 648 tp->GetColor(ThemeProperties::COLOR_TAB_THROBBER_WAITING); |
| 407 gfx::PaintThrobberSpinningAfterWaiting( | 649 gfx::PaintThrobberSpinningAfterWaiting( |
| 408 canvas, bounds, | 650 canvas, bounds, |
| 409 tp->GetColor(ThemeProperties::COLOR_TAB_THROBBER_SPINNING), | 651 tp->GetColor(ThemeProperties::COLOR_TAB_THROBBER_SPINNING), |
| 410 base::TimeTicks::Now() - loading_start_time_, &waiting_state_); | 652 base::TimeTicks::Now() - loading_start_time_, &waiting_state_); |
| 411 } | 653 } |
| 412 } | 654 } |
| 413 | 655 |
| 414 //////////////////////////////////////////////////////////////////////////////// | 656 //////////////////////////////////////////////////////////////////////////////// |
| 415 // Tab::ImageCacheEntryMetadata | |
| 416 | |
| 417 struct Tab::ImageCacheEntryMetadata { | |
| 418 ImageCacheEntryMetadata(int resource_id, | |
| 419 SkColor fill_color, | |
| 420 SkColor stroke_color, | |
| 421 ui::ScaleFactor scale_factor, | |
| 422 const gfx::Size& size); | |
| 423 | |
| 424 ~ImageCacheEntryMetadata(); | |
| 425 | |
| 426 // Making this a non-member would require a friend declaration in Tab. Bleh. | |
| 427 bool operator==(const ImageCacheEntryMetadata& rhs) const; | |
| 428 | |
| 429 int resource_id; // Only needed by pre-MD | |
| 430 SkColor fill_color; // Both colors only needed by MD | |
| 431 SkColor stroke_color; | |
| 432 ui::ScaleFactor scale_factor; | |
| 433 gfx::Size size; | |
| 434 }; | |
| 435 | |
| 436 Tab::ImageCacheEntryMetadata::ImageCacheEntryMetadata( | |
| 437 int resource_id, | |
| 438 SkColor fill_color, | |
| 439 SkColor stroke_color, | |
| 440 ui::ScaleFactor scale_factor, | |
| 441 const gfx::Size& size) | |
| 442 : resource_id(resource_id), | |
| 443 fill_color(fill_color), | |
| 444 stroke_color(stroke_color), | |
| 445 scale_factor(scale_factor), | |
| 446 size(size) { | |
| 447 DCHECK_NE(ui::SCALE_FACTOR_NONE, scale_factor); | |
| 448 | |
| 449 // Some fields are only relevant for pre-MD vs. MD. Erase the irrelevant ones | |
| 450 // so they don't cause incorrect cache misses. | |
| 451 // TODO(pkasting): Remove |resource_id| field when non-MD code is deleted. | |
| 452 if (ui::MaterialDesignController::IsModeMaterial()) | |
| 453 resource_id = 0; | |
| 454 else | |
| 455 fill_color = stroke_color = SK_ColorTRANSPARENT; | |
| 456 } | |
| 457 | |
| 458 Tab::ImageCacheEntryMetadata::~ImageCacheEntryMetadata() {} | |
| 459 | |
| 460 bool Tab::ImageCacheEntryMetadata::operator==( | |
| 461 const ImageCacheEntryMetadata& rhs) const { | |
| 462 return resource_id == rhs.resource_id && fill_color == rhs.fill_color && | |
| 463 stroke_color == rhs.stroke_color && scale_factor == rhs.scale_factor && | |
| 464 size == rhs.size; | |
| 465 } | |
| 466 | |
| 467 //////////////////////////////////////////////////////////////////////////////// | |
| 468 // Tab::ImageCacheEntry | |
| 469 | |
| 470 struct Tab::ImageCacheEntry { | |
| 471 ImageCacheEntry(const ImageCacheEntryMetadata& metadata, | |
| 472 const gfx::ImageSkia& image); | |
| 473 ~ImageCacheEntry(); | |
| 474 | |
| 475 ImageCacheEntryMetadata metadata; | |
| 476 gfx::ImageSkia image; | |
| 477 }; | |
| 478 | |
| 479 Tab::ImageCacheEntry::ImageCacheEntry(const ImageCacheEntryMetadata& metadata, | |
| 480 const gfx::ImageSkia& image) | |
| 481 : metadata(metadata), image(image) {} | |
| 482 | |
| 483 Tab::ImageCacheEntry::~ImageCacheEntry() {} | |
| 484 | |
| 485 //////////////////////////////////////////////////////////////////////////////// | |
| 486 // Tab, statics: | |
| 487 | |
| 488 // static | |
| 489 const char Tab::kViewClassName[] = "Tab"; | |
| 490 Tab::TabImages Tab::active_images_ = {0}; | |
| 491 Tab::TabImages Tab::inactive_images_ = {0}; | |
| 492 Tab::TabImages Tab::mask_images_ = {0}; | |
| 493 Tab::ImageCache* Tab::image_cache_ = NULL; | |
| 494 | |
| 495 //////////////////////////////////////////////////////////////////////////////// | |
| 496 // Tab, public: | 657 // Tab, public: |
| 497 | 658 |
| 659 // static | |
| 660 const char Tab::kViewClassName[] = "Tab"; | |
| 661 | |
| 498 Tab::Tab(TabController* controller, gfx::AnimationContainer* container) | 662 Tab::Tab(TabController* controller, gfx::AnimationContainer* container) |
| 499 : controller_(controller), | 663 : controller_(controller), |
| 500 closing_(false), | 664 closing_(false), |
| 501 dragging_(false), | 665 dragging_(false), |
| 502 detached_(false), | 666 detached_(false), |
| 503 favicon_hiding_offset_(0), | 667 favicon_hiding_offset_(0), |
| 504 immersive_loading_step_(0), | 668 immersive_loading_step_(0), |
| 505 should_display_crashed_favicon_(false), | 669 should_display_crashed_favicon_(false), |
| 506 pulse_animation_(new gfx::ThrobAnimation(this)), | 670 pulse_animation_(new gfx::ThrobAnimation(this)), |
| 507 crash_icon_animation_(new FaviconCrashAnimation(this)), | 671 crash_icon_animation_(new FaviconCrashAnimation(this)), |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 803 // When the window is maximized we don't want to shave off the edges or top | 967 // When the window is maximized we don't want to shave off the edges or top |
| 804 // shadow of the tab, such that the user can click anywhere along the top | 968 // shadow of the tab, such that the user can click anywhere along the top |
| 805 // edge of the screen to select a tab. Ditto for immersive fullscreen. | 969 // edge of the screen to select a tab. Ditto for immersive fullscreen. |
| 806 const views::Widget* widget = GetWidget(); | 970 const views::Widget* widget = GetWidget(); |
| 807 const bool extend_to_top = | 971 const bool extend_to_top = |
| 808 widget && (widget->IsMaximized() || widget->IsFullscreen()); | 972 widget && (widget->IsMaximized() || widget->IsFullscreen()); |
| 809 | 973 |
| 810 if (ui::MaterialDesignController::IsModeMaterial()) { | 974 if (ui::MaterialDesignController::IsModeMaterial()) { |
| 811 SkPath border; | 975 SkPath border; |
| 812 const float scale = GetWidget()->GetCompositor()->device_scale_factor(); | 976 const float scale = GetWidget()->GetCompositor()->device_scale_factor(); |
| 813 GetBorderPath(scale, extend_to_top, &border); | 977 GetBorderPath(scale, size(), extend_to_top, &border); |
| 814 mask->addPath(border, SkMatrix::MakeScale(1 / scale)); | 978 mask->addPath(border, SkMatrix::MakeScale(1 / scale)); |
| 815 } else { | 979 } else { |
| 816 // Hit mask constants. | 980 // Hit mask constants. |
| 817 const SkScalar kTabCapWidth = 15; | 981 const SkScalar kTabCapWidth = 15; |
| 818 const SkScalar kTabTopCurveWidth = 4; | 982 const SkScalar kTabTopCurveWidth = 4; |
| 819 const SkScalar kTabBottomCurveWidth = 3; | 983 const SkScalar kTabBottomCurveWidth = 3; |
| 820 #if defined(OS_MACOSX) | 984 #if defined(OS_MACOSX) |
| 821 // Mac's Cocoa UI doesn't have shadows. | 985 // Mac's Cocoa UI doesn't have shadows. |
| 822 const SkScalar kTabInset = 0; | 986 const SkScalar kTabInset = 0; |
| 823 #elif defined(TOOLKIT_VIEWS) | 987 #elif defined(TOOLKIT_VIEWS) |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1285 PaintTabBackgroundUsingFillId(canvas, false, fill_id, has_custom_image, | 1449 PaintTabBackgroundUsingFillId(canvas, false, fill_id, has_custom_image, |
| 1286 y_offset); | 1450 y_offset); |
| 1287 return; | 1451 return; |
| 1288 } | 1452 } |
| 1289 | 1453 |
| 1290 const ImageCacheEntryMetadata metadata( | 1454 const ImageCacheEntryMetadata metadata( |
| 1291 fill_id, tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB), | 1455 fill_id, tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB), |
| 1292 controller_->GetToolbarTopSeparatorColor(), | 1456 controller_->GetToolbarTopSeparatorColor(), |
| 1293 ui::GetSupportedScaleFactor(canvas->image_scale()), size()); | 1457 ui::GetSupportedScaleFactor(canvas->image_scale()), size()); |
| 1294 auto it = std::find_if( | 1458 auto it = std::find_if( |
| 1295 image_cache_->begin(), image_cache_->end(), | 1459 image_cache->begin(), image_cache->end(), |
| 1296 [&metadata](const ImageCacheEntry& e) { return e.metadata == metadata; }); | 1460 [&metadata](const ImageCacheEntry& e) { return e.metadata == metadata; }); |
| 1297 if (it == image_cache_->end()) { | 1461 if (it == image_cache->end()) { |
| 1298 gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false); | 1462 gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false); |
| 1299 PaintTabBackgroundUsingFillId(&tmp_canvas, false, fill_id, false, y_offset); | 1463 PaintTabBackgroundUsingFillId(&tmp_canvas, false, fill_id, false, y_offset); |
| 1300 image_cache_->emplace_front(metadata, | 1464 image_cache->emplace_front(metadata, |
| 1301 gfx::ImageSkia(tmp_canvas.ExtractImageRep())); | 1465 gfx::ImageSkia(tmp_canvas.ExtractImageRep())); |
| 1302 if (image_cache_->size() > kMaxImageCacheSize) | 1466 if (image_cache->size() > kMaxImageCacheSize) |
| 1303 image_cache_->pop_back(); | 1467 image_cache->pop_back(); |
| 1304 it = image_cache_->begin(); | 1468 it = image_cache->begin(); |
| 1305 } | 1469 } |
| 1306 canvas->DrawImageInt(it->image, 0, 0); | 1470 canvas->DrawImageInt(it->image, 0, 0); |
| 1307 } | 1471 } |
| 1308 | 1472 |
| 1309 void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* canvas, | 1473 void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* canvas, |
| 1310 bool is_active, | 1474 bool is_active, |
| 1311 int fill_id, | 1475 int fill_id, |
| 1312 bool has_custom_image, | 1476 bool has_custom_image, |
| 1313 int y_offset) { | 1477 int y_offset) { |
| 1314 const ui::ThemeProvider* tp = GetThemeProvider(); | 1478 const ui::ThemeProvider* tp = GetThemeProvider(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1326 SkPoint hover_location(PointToSkPoint(hover_controller_.location())); | 1490 SkPoint hover_location(PointToSkPoint(hover_controller_.location())); |
| 1327 const SkColor hover_color = | 1491 const SkColor hover_color = |
| 1328 SkColorSetA(toolbar_color, hover_controller_.GetAlpha()); | 1492 SkColorSetA(toolbar_color, hover_controller_.GetAlpha()); |
| 1329 | 1493 |
| 1330 if (ui::MaterialDesignController::IsModeMaterial()) { | 1494 if (ui::MaterialDesignController::IsModeMaterial()) { |
| 1331 gfx::ScopedCanvas scoped_canvas(canvas); | 1495 gfx::ScopedCanvas scoped_canvas(canvas); |
| 1332 const float scale = canvas->UndoDeviceScaleFactor(); | 1496 const float scale = canvas->UndoDeviceScaleFactor(); |
| 1333 | 1497 |
| 1334 // Draw the fill. | 1498 // Draw the fill. |
| 1335 SkPath fill; | 1499 SkPath fill; |
| 1336 GetFillPath(scale, &fill); | 1500 GetFillPath(scale, size(), &fill); |
| 1337 SkPaint paint; | 1501 SkPaint paint; |
| 1338 paint.setAntiAlias(true); | 1502 paint.setAntiAlias(true); |
| 1339 { | 1503 { |
| 1340 gfx::ScopedCanvas clip_scoper(canvas); | 1504 gfx::ScopedCanvas clip_scoper(canvas); |
| 1341 canvas->ClipPath(fill, true); | 1505 canvas->ClipPath(fill, true); |
| 1342 if (has_custom_image) { | 1506 if (has_custom_image) { |
| 1343 gfx::ScopedCanvas scale_scoper(canvas); | 1507 gfx::ScopedCanvas scale_scoper(canvas); |
| 1344 canvas->sk_canvas()->scale(scale, scale); | 1508 canvas->sk_canvas()->scale(scale, scale); |
| 1345 canvas->TileImageInt(*fill_image, x_offset, y_offset, 0, 0, width(), | 1509 canvas->TileImageInt(*fill_image, x_offset, y_offset, 0, 0, width(), |
| 1346 height()); | 1510 height()); |
| 1347 } else { | 1511 } else { |
| 1348 paint.setColor( | 1512 paint.setColor( |
| 1349 is_active ? toolbar_color | 1513 is_active ? toolbar_color |
| 1350 : tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB)); | 1514 : tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB)); |
| 1351 canvas->DrawRect(gfx::ScaleToEnclosingRect(GetLocalBounds(), scale), | 1515 canvas->DrawRect(gfx::ScaleToEnclosingRect(GetLocalBounds(), scale), |
| 1352 paint); | 1516 paint); |
| 1353 } | 1517 } |
| 1354 if (draw_hover) { | 1518 if (draw_hover) { |
| 1355 hover_location.scale(SkFloatToScalar(scale)); | 1519 hover_location.scale(SkFloatToScalar(scale)); |
| 1356 DrawHighlight(canvas, hover_location, radius * scale, hover_color); | 1520 DrawHighlight(canvas, hover_location, radius * scale, hover_color); |
| 1357 } | 1521 } |
| 1358 } | 1522 } |
| 1359 | 1523 |
| 1360 // Draw the stroke. | 1524 // Draw the stroke. |
| 1361 SkPath stroke; | 1525 SkPath stroke; |
| 1362 GetBorderPath(scale, false, &stroke); | 1526 GetBorderPath(scale, size(), false, &stroke); |
| 1363 Op(stroke, fill, kDifference_SkPathOp, &stroke); | 1527 Op(stroke, fill, kDifference_SkPathOp, &stroke); |
| 1364 if (!is_active) { | 1528 if (!is_active) { |
| 1365 // Clip out the bottom line; this will be drawn for us by | 1529 // Clip out the bottom line; this will be drawn for us by |
| 1366 // TabStrip::PaintChildren(). | 1530 // TabStrip::PaintChildren(). |
| 1367 canvas->sk_canvas()->clipRect( | 1531 canvas->sk_canvas()->clipRect( |
| 1368 SkRect::MakeWH(width() * scale, height() * scale - 1)); | 1532 SkRect::MakeWH(width() * scale, height() * scale - 1)); |
| 1369 } | 1533 } |
| 1370 paint.setColor(controller_->GetToolbarTopSeparatorColor()); | 1534 paint.setColor(controller_->GetToolbarTopSeparatorColor()); |
| 1371 canvas->DrawPath(stroke, paint); | 1535 canvas->DrawPath(stroke, paint); |
| 1372 } else { | 1536 } else { |
| 1373 if (draw_hover) { | 1537 if (draw_hover) { |
| 1374 // Draw everything to a temporary canvas so we can extract an image for | 1538 // Draw everything to a temporary canvas so we can extract an image for |
| 1375 // use in masking the hover glow. | 1539 // use in masking the hover glow. |
| 1376 gfx::Canvas background_canvas(size(), canvas->image_scale(), false); | 1540 gfx::Canvas background_canvas(size(), canvas->image_scale(), false); |
| 1377 PaintTabFill(&background_canvas, fill_image, x_offset, y_offset, | 1541 PaintTabFill(&background_canvas, fill_image, x_offset, y_offset, size(), |
| 1378 is_active); | 1542 is_active); |
| 1379 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); | 1543 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); |
| 1380 canvas->DrawImageInt(background_image, 0, 0); | 1544 canvas->DrawImageInt(background_image, 0, 0); |
| 1381 | 1545 |
| 1382 gfx::Canvas hover_canvas(size(), canvas->image_scale(), false); | 1546 gfx::Canvas hover_canvas(size(), canvas->image_scale(), false); |
| 1383 DrawHighlight(&hover_canvas, hover_location, radius, hover_color); | 1547 DrawHighlight(&hover_canvas, hover_location, radius, hover_color); |
| 1384 gfx::ImageSkia result = gfx::ImageSkiaOperations::CreateMaskedImage( | 1548 gfx::ImageSkia result = gfx::ImageSkiaOperations::CreateMaskedImage( |
| 1385 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); | 1549 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); |
| 1386 canvas->DrawImageInt(result, 0, 0); | 1550 canvas->DrawImageInt(result, 0, 0); |
| 1387 } else { | 1551 } else { |
| 1388 PaintTabFill(canvas, fill_image, x_offset, y_offset, is_active); | 1552 PaintTabFill(canvas, fill_image, x_offset, y_offset, size(), is_active); |
| 1389 } | 1553 } |
| 1390 | 1554 |
| 1391 // Now draw the stroke, highlights, and shadows around the tab edge. | 1555 // Now draw the stroke, highlights, and shadows around the tab edge. |
| 1392 TabImages* stroke_images = is_active ? &active_images_ : &inactive_images_; | 1556 TabImages* stroke_images = is_active ? &active_images : &inactive_images; |
| 1393 canvas->DrawImageInt(*stroke_images->image_l, 0, 0); | 1557 canvas->DrawImageInt(*stroke_images->image_l, 0, 0); |
| 1394 canvas->TileImageInt( | 1558 canvas->TileImageInt( |
| 1395 *stroke_images->image_c, stroke_images->l_width, 0, | 1559 *stroke_images->image_c, stroke_images->l_width, 0, |
| 1396 width() - stroke_images->l_width - stroke_images->r_width, height()); | 1560 width() - stroke_images->l_width - stroke_images->r_width, height()); |
| 1397 canvas->DrawImageInt(*stroke_images->image_r, | 1561 canvas->DrawImageInt(*stroke_images->image_r, |
| 1398 width() - stroke_images->r_width, 0); | 1562 width() - stroke_images->r_width, 0); |
| 1399 } | 1563 } |
| 1400 } | 1564 } |
| 1401 | 1565 |
| 1402 void Tab::PaintTabFill(gfx::Canvas* canvas, | |
| 1403 gfx::ImageSkia* fill_image, | |
| 1404 int x_offset, | |
| 1405 int y_offset, | |
| 1406 bool is_active) { | |
| 1407 const gfx::Insets tab_insets(GetLayoutInsets(TAB)); | |
| 1408 // If this isn't the foreground tab, don't draw over the toolbar, but do | |
| 1409 // include the 1 px divider stroke at the bottom. | |
| 1410 const int toolbar_overlap = is_active ? 0 : (tab_insets.bottom() - 1); | |
| 1411 | |
| 1412 // Draw left edge. | |
| 1413 gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( | |
| 1414 *fill_image, x_offset, y_offset, mask_images_.l_width, height()); | |
| 1415 gfx::ImageSkia theme_l = | |
| 1416 gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *mask_images_.image_l); | |
| 1417 canvas->DrawImageInt( | |
| 1418 theme_l, 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, 0, 0, | |
| 1419 theme_l.width(), theme_l.height() - toolbar_overlap, false); | |
| 1420 | |
| 1421 // Draw right edge. | |
| 1422 gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( | |
| 1423 *fill_image, x_offset + width() - mask_images_.r_width, y_offset, | |
| 1424 mask_images_.r_width, height()); | |
| 1425 gfx::ImageSkia theme_r = | |
| 1426 gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *mask_images_.image_r); | |
| 1427 canvas->DrawImageInt(theme_r, 0, 0, theme_r.width(), | |
| 1428 theme_r.height() - toolbar_overlap, | |
| 1429 width() - theme_r.width(), 0, theme_r.width(), | |
| 1430 theme_r.height() - toolbar_overlap, false); | |
| 1431 | |
| 1432 // Draw center. Instead of masking out the top portion we simply skip over it | |
| 1433 // by incrementing by the top padding, since it's a simple rectangle. | |
| 1434 canvas->TileImageInt(*fill_image, x_offset + mask_images_.l_width, | |
| 1435 y_offset + tab_insets.top(), mask_images_.l_width, | |
| 1436 tab_insets.top(), | |
| 1437 width() - mask_images_.l_width - mask_images_.r_width, | |
| 1438 height() - tab_insets.top() - toolbar_overlap); | |
| 1439 } | |
| 1440 | |
| 1441 void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( | 1566 void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( |
| 1442 gfx::Canvas* canvas, | 1567 gfx::Canvas* canvas, |
| 1443 const gfx::Rect& favicon_draw_bounds) { | 1568 const gfx::Rect& favicon_draw_bounds) { |
| 1444 // The pinned tab title changed indicator consists of two parts: | 1569 // The pinned tab title changed indicator consists of two parts: |
| 1445 // . a clear (totally transparent) part over the bottom right (or left in rtl) | 1570 // . a clear (totally transparent) part over the bottom right (or left in rtl) |
| 1446 // of the favicon. This is done by drawing the favicon to a canvas, then | 1571 // of the favicon. This is done by drawing the favicon to a canvas, then |
| 1447 // drawing the clear part on top of the favicon. | 1572 // drawing the clear part on top of the favicon. |
| 1448 // . a circle in the bottom right (or left in rtl) of the favicon. | 1573 // . a circle in the bottom right (or left in rtl) of the favicon. |
| 1449 if (!favicon_.isNull()) { | 1574 if (!favicon_.isNull()) { |
| 1450 const float kIndicatorCropRadius = 4.5; | 1575 const float kIndicatorCropRadius = 4.5; |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1667 if (bounds.IsEmpty()) | 1792 if (bounds.IsEmpty()) |
| 1668 return; | 1793 return; |
| 1669 | 1794 |
| 1670 // Extends the area to the bottom when the crash animation is in progress. | 1795 // Extends the area to the bottom when the crash animation is in progress. |
| 1671 if (crash_icon_animation_->is_animating()) | 1796 if (crash_icon_animation_->is_animating()) |
| 1672 bounds.set_height(height() - bounds.y()); | 1797 bounds.set_height(height() - bounds.y()); |
| 1673 bounds.set_x(GetMirroredXForRect(bounds)); | 1798 bounds.set_x(GetMirroredXForRect(bounds)); |
| 1674 SchedulePaintInRect(bounds); | 1799 SchedulePaintInRect(bounds); |
| 1675 } | 1800 } |
| 1676 | 1801 |
| 1677 void Tab::GetFillPath(float scale, SkPath* fill) const { | |
| 1678 const float right = width() * scale; | |
| 1679 // The bottom of the tab needs to be pixel-aligned or else when we call | |
| 1680 // ClipPath with anti-aliasing enabled it can cause artifacts. | |
| 1681 const float bottom = std::ceil(height() * scale); | |
| 1682 const float unscaled_endcap_width = GetUnscaledEndcapWidth(); | |
| 1683 | |
| 1684 fill->moveTo(right - 1, bottom); | |
| 1685 fill->rCubicTo(-0.75 * scale, 0, -1.625 * scale, -0.5 * scale, -2 * scale, | |
| 1686 -1.5 * scale); | |
| 1687 fill->lineTo(right - 1 - (unscaled_endcap_width - 2) * scale, 2.5 * scale); | |
| 1688 // Prevent overdraw in the center near minimum width (only happens if | |
| 1689 // scale < 2). We could instead avoid this by increasing the tab inset | |
| 1690 // values, but that would shift all the content inward as well, unless we | |
| 1691 // then overlapped the content on the endcaps, by which point we'd have a | |
| 1692 // huge mess. | |
| 1693 const float scaled_endcap_width = 1 + unscaled_endcap_width * scale; | |
| 1694 const float overlap = scaled_endcap_width * 2 - right; | |
| 1695 const float offset = (overlap > 0) ? (overlap / 2) : 0; | |
| 1696 fill->rCubicTo(-0.375 * scale, -1 * scale, -1.25 * scale + offset, | |
| 1697 -1.5 * scale, -2 * scale + offset, -1.5 * scale); | |
| 1698 if (overlap < 0) | |
| 1699 fill->lineTo(scaled_endcap_width, scale); | |
| 1700 fill->rCubicTo(-0.75 * scale, 0, -1.625 * scale - offset, 0.5 * scale, | |
| 1701 -2 * scale - offset, 1.5 * scale); | |
| 1702 fill->lineTo(1 + 2 * scale, bottom - 1.5 * scale); | |
| 1703 fill->rCubicTo(-0.375 * scale, scale, -1.25 * scale, 1.5 * scale, -2 * scale, | |
| 1704 1.5 * scale); | |
| 1705 fill->close(); | |
| 1706 } | |
| 1707 | |
| 1708 void Tab::GetBorderPath(float scale, bool extend_to_top, SkPath* path) const { | |
| 1709 const float top = scale - 1; | |
| 1710 const float right = width() * scale; | |
| 1711 const float bottom = height() * scale; | |
| 1712 const float unscaled_endcap_width = GetUnscaledEndcapWidth(); | |
| 1713 | |
| 1714 path->moveTo(0, bottom); | |
| 1715 path->rLineTo(0, -1); | |
| 1716 path->rCubicTo(0.75 * scale, 0, 1.625 * scale, -0.5 * scale, 2 * scale, | |
| 1717 -1.5 * scale); | |
| 1718 path->lineTo((unscaled_endcap_width - 2) * scale, top + 1.5 * scale); | |
| 1719 if (extend_to_top) { | |
| 1720 // Create the vertical extension by extending the side diagonals until they | |
| 1721 // reach the top of the bounds. | |
| 1722 const float dy = 2.5 * scale - 1; | |
| 1723 const float dx = GetInverseDiagonalSlope() * dy; | |
| 1724 path->rLineTo(dx, -dy); | |
| 1725 path->lineTo(right - (unscaled_endcap_width - 2) * scale - dx, 0); | |
| 1726 path->rLineTo(dx, dy); | |
| 1727 } else { | |
| 1728 path->rCubicTo(0.375 * scale, -scale, 1.25 * scale, -1.5 * scale, 2 * scale, | |
| 1729 -1.5 * scale); | |
| 1730 path->lineTo(right - unscaled_endcap_width * scale, top); | |
| 1731 path->rCubicTo(0.75 * scale, 0, 1.625 * scale, 0.5 * scale, 2 * scale, | |
| 1732 1.5 * scale); | |
| 1733 } | |
| 1734 path->lineTo(right - 2 * scale, bottom - 1 - 1.5 * scale); | |
| 1735 path->rCubicTo(0.375 * scale, scale, 1.25 * scale, 1.5 * scale, 2 * scale, | |
| 1736 1.5 * scale); | |
| 1737 path->rLineTo(0, 1); | |
| 1738 path->close(); | |
| 1739 } | |
| 1740 | |
| 1741 gfx::Rect Tab::GetImmersiveBarRect() const { | 1802 gfx::Rect Tab::GetImmersiveBarRect() const { |
| 1742 // The main bar is as wide as the normal tab's horizontal top line. | 1803 // The main bar is as wide as the normal tab's horizontal top line. |
| 1743 // This top line of the tab extends a few pixels left and right of the | 1804 // This top line of the tab extends a few pixels left and right of the |
| 1744 // center image due to pixels in the rounded corner images. | 1805 // center image due to pixels in the rounded corner images. |
| 1745 const int kBarPadding = 1; | 1806 const int kBarPadding = 1; |
| 1746 int main_bar_left = active_images_.l_width - kBarPadding; | 1807 int main_bar_left = active_images.l_width - kBarPadding; |
| 1747 int main_bar_right = width() - active_images_.r_width + kBarPadding; | 1808 int main_bar_right = width() - active_images.r_width + kBarPadding; |
| 1748 return gfx::Rect( | 1809 return gfx::Rect( |
| 1749 main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight); | 1810 main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight); |
| 1750 } | 1811 } |
| 1751 | |
| 1752 //////////////////////////////////////////////////////////////////////////////// | |
| 1753 // Tab, private static: | |
| 1754 | |
| 1755 // static | |
| 1756 void Tab::InitTabResources() { | |
| 1757 static bool initialized = false; | |
| 1758 if (initialized) | |
| 1759 return; | |
| 1760 | |
| 1761 initialized = true; | |
| 1762 image_cache_ = new ImageCache(); | |
| 1763 | |
| 1764 // Load the tab images once now, and maybe again later if the theme changes. | |
| 1765 LoadTabImages(); | |
| 1766 } | |
| 1767 | |
| 1768 // static | |
| 1769 void Tab::LoadTabImages() { | |
| 1770 image_cache_->clear(); | |
| 1771 | |
| 1772 // We're not letting people override tab images just yet. | |
| 1773 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 1774 | |
| 1775 active_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_LEFT); | |
| 1776 active_images_.image_c = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_CENTER); | |
| 1777 active_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_RIGHT); | |
| 1778 active_images_.l_width = active_images_.image_l->width(); | |
| 1779 active_images_.r_width = active_images_.image_r->width(); | |
| 1780 | |
| 1781 inactive_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_LEFT); | |
| 1782 inactive_images_.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); | |
| 1783 inactive_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); | |
| 1784 inactive_images_.l_width = inactive_images_.image_l->width(); | |
| 1785 inactive_images_.r_width = inactive_images_.image_r->width(); | |
| 1786 | |
| 1787 mask_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); | |
| 1788 mask_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); | |
| 1789 mask_images_.l_width = mask_images_.image_l->width(); | |
| 1790 mask_images_.r_width = mask_images_.image_r->width(); | |
| 1791 } | |
| OLD | NEW |