Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(517)

Side by Side Diff: chrome/browser/ui/views/tabs/tab.cc

Issue 2150013002: Move private static members and methods into namespace (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/ui/views/tabs/tab.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/tabs/tab.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698