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 26 matching lines...) Expand all Loading... |
37 #include "ui/base/material_design/material_design_controller.h" | 37 #include "ui/base/material_design/material_design_controller.h" |
38 #include "ui/base/models/list_selection_model.h" | 38 #include "ui/base/models/list_selection_model.h" |
39 #include "ui/base/resource/resource_bundle.h" | 39 #include "ui/base/resource/resource_bundle.h" |
40 #include "ui/base/theme_provider.h" | 40 #include "ui/base/theme_provider.h" |
41 #include "ui/gfx/animation/animation_container.h" | 41 #include "ui/gfx/animation/animation_container.h" |
42 #include "ui/gfx/animation/throb_animation.h" | 42 #include "ui/gfx/animation/throb_animation.h" |
43 #include "ui/gfx/canvas.h" | 43 #include "ui/gfx/canvas.h" |
44 #include "ui/gfx/color_analysis.h" | 44 #include "ui/gfx/color_analysis.h" |
45 #include "ui/gfx/favicon_size.h" | 45 #include "ui/gfx/favicon_size.h" |
46 #include "ui/gfx/geometry/rect_conversions.h" | 46 #include "ui/gfx/geometry/rect_conversions.h" |
| 47 #include "ui/gfx/image/canvas_image_source.h" |
47 #include "ui/gfx/image/image_skia_operations.h" | 48 #include "ui/gfx/image/image_skia_operations.h" |
48 #include "ui/gfx/paint_vector_icon.h" | 49 #include "ui/gfx/paint_vector_icon.h" |
49 #include "ui/gfx/path.h" | 50 #include "ui/gfx/path.h" |
50 #include "ui/gfx/scoped_canvas.h" | 51 #include "ui/gfx/scoped_canvas.h" |
51 #include "ui/gfx/skia_util.h" | 52 #include "ui/gfx/skia_util.h" |
52 #include "ui/gfx/vector_icons_public.h" | 53 #include "ui/gfx/vector_icons_public.h" |
53 #include "ui/resources/grit/ui_resources.h" | 54 #include "ui/resources/grit/ui_resources.h" |
54 #include "ui/views/border.h" | 55 #include "ui/views/border.h" |
55 #include "ui/views/controls/button/image_button.h" | 56 #include "ui/views/controls/button/image_button.h" |
56 #include "ui/views/controls/label.h" | 57 #include "ui/views/controls/label.h" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 // Number of steps in the immersive mode loading animation. | 115 // Number of steps in the immersive mode loading animation. |
115 const int kImmersiveLoadingStepCount = 32; | 116 const int kImmersiveLoadingStepCount = 32; |
116 | 117 |
117 const char kTabCloseButtonName[] = "TabCloseButton"; | 118 const char kTabCloseButtonName[] = "TabCloseButton"; |
118 | 119 |
119 // Desaturate favicon HSL shift values. | 120 // Desaturate favicon HSL shift values. |
120 const double kDesaturateHue = -1.0; | 121 const double kDesaturateHue = -1.0; |
121 const double kDesaturateSaturation = 0.0; | 122 const double kDesaturateSaturation = 0.0; |
122 const double kDesaturateLightness = 0.6; | 123 const double kDesaturateLightness = 0.6; |
123 | 124 |
124 // Parameters for PaintTabBackgroundUsingParams(). | 125 // Parameters for PaintTabFill/StrokeUsingParams(). |
125 struct PaintBackgroundParams { | 126 struct PaintBackgroundParams { |
126 PaintBackgroundParams(bool is_active, | 127 PaintBackgroundParams(bool is_active, |
127 gfx::ImageSkia* fill_image_ptr, | 128 gfx::ImageSkia* fill_image, |
128 bool has_custom_image, | 129 bool has_custom_image, |
129 gfx::Rect rect, | 130 const gfx::Rect& rect, |
130 SkColor stroke_color, | 131 SkColor stroke_color, |
131 SkColor toolbar_color, | 132 SkColor toolbar_color, |
132 SkColor background_tab_color) | 133 SkColor background_tab_color, |
| 134 bool draw_hover, |
| 135 const gfx::Point& hover_location, |
| 136 SkAlpha hover_alpha) |
133 : is_active(is_active), | 137 : is_active(is_active), |
134 fill_image(fill_image_ptr ? *fill_image_ptr : gfx::ImageSkia()), | 138 fill_image(fill_image ? *fill_image : gfx::ImageSkia()), |
135 has_custom_image(has_custom_image), | |
136 rect(rect), | 139 rect(rect), |
137 stroke_color(stroke_color), | 140 stroke_color(stroke_color), |
138 toolbar_color(toolbar_color), | 141 toolbar_color(toolbar_color), |
139 background_tab_color(background_tab_color) {} | 142 background_tab_color(background_tab_color), |
| 143 draw_hover(draw_hover), |
| 144 hover_location(PointToSkPoint(hover_location)), |
| 145 hover_alpha(hover_alpha) {} |
140 | 146 |
141 const bool is_active; | 147 const bool is_active; |
142 const gfx::ImageSkia fill_image; | 148 const gfx::ImageSkia fill_image; |
143 const bool has_custom_image; | |
144 const gfx::Rect rect; | 149 const gfx::Rect rect; |
145 const SkColor stroke_color; | 150 const SkColor stroke_color; |
146 const SkColor toolbar_color; | 151 const SkColor toolbar_color; |
147 const SkColor background_tab_color; | 152 const SkColor background_tab_color; |
| 153 const bool draw_hover; |
| 154 const SkPoint hover_location; |
| 155 const SkAlpha hover_alpha; |
148 }; | 156 }; |
149 | 157 |
| 158 void PaintTabFillUsingParams(gfx::Canvas* canvas, |
| 159 const PaintBackgroundParams& params); |
| 160 |
| 161 void PaintTabStrokeUsingParams(gfx::Canvas* canvas, |
| 162 const PaintBackgroundParams& params); |
| 163 |
| 164 //////////////////////////////////////////////////////////////////////////////// |
| 165 // TabImageSource |
| 166 // |
| 167 // This subclass of CanvasImageSource allows the inactive tab image to be cached |
| 168 // once for each requested scale factor. |
| 169 class TabImageSource : public gfx::CanvasImageSource { |
| 170 public: |
| 171 enum UseCanvas { FILL, STROKE, BOTH }; |
| 172 |
| 173 TabImageSource(UseCanvas use_canvas, Tab* tab, int fill_id, int y_offset); |
| 174 ~TabImageSource() override {} |
| 175 |
| 176 // gfx::CanvasImageSource override. |
| 177 void Draw(gfx::Canvas* canvas) override; |
| 178 bool HasRepresentationAtAllScales() const override { return true; } |
| 179 |
| 180 private: |
| 181 const UseCanvas use_canvas_; |
| 182 const PaintBackgroundParams params_; |
| 183 |
| 184 DISALLOW_COPY_AND_ASSIGN(TabImageSource); |
| 185 }; |
| 186 |
| 187 TabImageSource::TabImageSource(UseCanvas use_canvas, |
| 188 Tab* tab, |
| 189 int fill_id, |
| 190 int y_offset) |
| 191 : gfx::CanvasImageSource(tab->size(), true), |
| 192 use_canvas_(use_canvas), |
| 193 params_(false, |
| 194 tab->GetThemeProvider()->GetImageSkiaNamed(fill_id), |
| 195 false, |
| 196 gfx::Rect(gfx::Point(0, y_offset), tab->size()), |
| 197 tab->controller()->GetToolbarTopSeparatorColor(), |
| 198 tab->GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR), |
| 199 tab->GetThemeProvider()->GetColor( |
| 200 ThemeProperties::COLOR_BACKGROUND_TAB), |
| 201 false, |
| 202 gfx::Point(), |
| 203 255) {} |
| 204 |
| 205 void TabImageSource::Draw(gfx::Canvas* canvas) { |
| 206 if (use_canvas_ != STROKE) |
| 207 PaintTabFillUsingParams(canvas, params_); |
| 208 if (use_canvas_ != FILL) |
| 209 PaintTabStrokeUsingParams(canvas, params_); |
| 210 } |
| 211 |
150 //////////////////////////////////////////////////////////////////////////////// | 212 //////////////////////////////////////////////////////////////////////////////// |
151 // ImageCacheEntryMetadata | 213 // ImageCacheEntryMetadata |
152 // | 214 // |
153 // All metadata necessary to uniquely identify a cached image. | 215 // All metadata necessary to uniquely identify a cached image. |
154 struct ImageCacheEntryMetadata { | 216 struct ImageCacheEntryMetadata { |
155 ImageCacheEntryMetadata(int resource_id, | 217 ImageCacheEntryMetadata(int resource_id, |
156 SkColor fill_color, | 218 SkColor fill_color, |
157 SkColor stroke_color, | 219 SkColor stroke_color, |
158 bool use_fill_and_stroke_images, | 220 bool use_fill_and_stroke_images, |
159 ui::ScaleFactor scale_factor, | |
160 const gfx::Size& size); | 221 const gfx::Size& size); |
161 | 222 |
162 ~ImageCacheEntryMetadata(); | 223 ~ImageCacheEntryMetadata(); |
163 | 224 |
164 bool operator==(const ImageCacheEntryMetadata& rhs) const; | 225 bool operator==(const ImageCacheEntryMetadata& rhs) const; |
165 | 226 |
166 int resource_id; // Only needed by pre-MD | 227 int resource_id; // Only needed by pre-MD |
167 SkColor fill_color; // Both colors only needed by MD | 228 SkColor fill_color; // Both colors only needed by MD |
168 SkColor stroke_color; | 229 SkColor stroke_color; |
169 bool use_fill_and_stroke_images; | 230 bool use_fill_and_stroke_images; |
170 ui::ScaleFactor scale_factor; | |
171 gfx::Size size; | 231 gfx::Size size; |
172 }; | 232 }; |
173 | 233 |
174 ImageCacheEntryMetadata::ImageCacheEntryMetadata( | 234 ImageCacheEntryMetadata::ImageCacheEntryMetadata( |
175 int resource_id, | 235 int resource_id, |
176 SkColor fill_color, | 236 SkColor fill_color, |
177 SkColor stroke_color, | 237 SkColor stroke_color, |
178 bool use_fill_and_stroke_images, | 238 bool use_fill_and_stroke_images, |
179 ui::ScaleFactor scale_factor, | |
180 const gfx::Size& size) | 239 const gfx::Size& size) |
181 : resource_id(resource_id), | 240 : resource_id(resource_id), |
182 fill_color(fill_color), | 241 fill_color(fill_color), |
183 stroke_color(stroke_color), | 242 stroke_color(stroke_color), |
184 use_fill_and_stroke_images(use_fill_and_stroke_images), | 243 use_fill_and_stroke_images(use_fill_and_stroke_images), |
185 scale_factor(scale_factor), | |
186 size(size) { | 244 size(size) { |
187 DCHECK_NE(ui::SCALE_FACTOR_NONE, scale_factor); | |
188 | |
189 // Some fields are only relevant for pre-MD vs. MD. Erase the irrelevant ones | 245 // Some fields are only relevant for pre-MD vs. MD. Erase the irrelevant ones |
190 // so they don't cause incorrect cache misses. | 246 // so they don't cause incorrect cache misses. |
191 // TODO(pkasting): Remove |resource_id| field when non-MD code is deleted. | 247 // TODO(pkasting): Remove |resource_id| field when non-MD code is deleted. |
192 if (ui::MaterialDesignController::IsModeMaterial()) | 248 if (ui::MaterialDesignController::IsModeMaterial()) |
193 resource_id = 0; | 249 resource_id = 0; |
194 else | 250 else |
195 fill_color = stroke_color = SK_ColorTRANSPARENT; | 251 fill_color = stroke_color = SK_ColorTRANSPARENT; |
196 } | 252 } |
197 | 253 |
198 ImageCacheEntryMetadata::~ImageCacheEntryMetadata() {} | 254 ImageCacheEntryMetadata::~ImageCacheEntryMetadata() {} |
199 | 255 |
200 bool ImageCacheEntryMetadata::operator==( | 256 bool ImageCacheEntryMetadata::operator==( |
201 const ImageCacheEntryMetadata& rhs) const { | 257 const ImageCacheEntryMetadata& rhs) const { |
202 return resource_id == rhs.resource_id && fill_color == rhs.fill_color && | 258 return resource_id == rhs.resource_id && fill_color == rhs.fill_color && |
203 stroke_color == rhs.stroke_color && | 259 stroke_color == rhs.stroke_color && |
204 use_fill_and_stroke_images == rhs.use_fill_and_stroke_images && | 260 use_fill_and_stroke_images == rhs.use_fill_and_stroke_images && |
205 scale_factor == rhs.scale_factor && size == rhs.size; | 261 size == rhs.size; |
206 } | 262 } |
207 | 263 |
208 //////////////////////////////////////////////////////////////////////////////// | 264 //////////////////////////////////////////////////////////////////////////////// |
209 // ImageCacheEntry and cache management | 265 // ImageCacheEntry and cache management |
210 // | 266 // |
211 // A cached image and the metadata used to generate it. | 267 // A cached image and the metadata used to generate it. |
212 struct ImageCacheEntry { | 268 struct ImageCacheEntry { |
213 ImageCacheEntry(const ImageCacheEntryMetadata& metadata, | 269 ImageCacheEntry(const ImageCacheEntryMetadata& metadata, |
214 const gfx::ImageSkia& fill_image, | 270 Tab* tab, |
215 const gfx::ImageSkia& stroke_image); | 271 int fill_id, |
| 272 int y_offset); |
216 ~ImageCacheEntry(); | 273 ~ImageCacheEntry(); |
217 | 274 |
218 ImageCacheEntryMetadata metadata; | 275 ImageCacheEntryMetadata metadata; |
219 gfx::ImageSkia fill_image; | 276 gfx::ImageSkia fill_image; |
220 gfx::ImageSkia stroke_image; | 277 gfx::ImageSkia stroke_image; |
221 }; | 278 }; |
222 | 279 |
223 ImageCacheEntry::ImageCacheEntry(const ImageCacheEntryMetadata& metadata, | 280 ImageCacheEntry::ImageCacheEntry(const ImageCacheEntryMetadata& metadata, |
224 const gfx::ImageSkia& fill_image, | 281 Tab* tab, |
225 const gfx::ImageSkia& stroke_image) | 282 int fill_id, |
226 : metadata(metadata), fill_image(fill_image), stroke_image(stroke_image) {} | 283 int y_offset) |
| 284 : metadata(metadata) { |
| 285 if (metadata.use_fill_and_stroke_images) { |
| 286 fill_image = gfx::ImageSkia( |
| 287 new TabImageSource(TabImageSource::FILL, tab, fill_id, y_offset), |
| 288 tab->size()); |
| 289 } |
| 290 TabImageSource::UseCanvas use = metadata.use_fill_and_stroke_images |
| 291 ? TabImageSource::STROKE |
| 292 : TabImageSource::BOTH; |
| 293 stroke_image = gfx::ImageSkia(new TabImageSource(use, tab, fill_id, y_offset), |
| 294 tab->size()); |
| 295 } |
227 | 296 |
228 ImageCacheEntry::~ImageCacheEntry() {} | 297 ImageCacheEntry::~ImageCacheEntry() {} |
229 | 298 |
230 typedef std::list<ImageCacheEntry> ImageCache; | 299 typedef std::list<ImageCacheEntry> ImageCache; |
231 | 300 |
232 // As the majority of the tabs are inactive, and painting tabs is slowish, | 301 // As the majority of the tabs are inactive, and painting tabs is slowish, |
233 // we cache a handful of the inactive tab backgrounds here. | 302 // we cache a handful of the inactive tab backgrounds here. |
234 static ImageCache* g_image_cache = nullptr; | 303 static ImageCache* g_image_cache = nullptr; |
235 | 304 |
236 struct TabImages { | 305 struct TabImages { |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 theme_r.height() - toolbar_overlap, false); | 548 theme_r.height() - toolbar_overlap, false); |
480 | 549 |
481 // Draw center. Instead of masking out the top portion we simply skip over it | 550 // Draw center. Instead of masking out the top portion we simply skip over it |
482 // by incrementing by the top padding, since it's a simple rectangle. | 551 // by incrementing by the top padding, since it's a simple rectangle. |
483 rect.Inset(g_mask_images.l_width, tab_insets.top(), g_mask_images.r_width, | 552 rect.Inset(g_mask_images.l_width, tab_insets.top(), g_mask_images.r_width, |
484 toolbar_overlap); | 553 toolbar_overlap); |
485 canvas->TileImageInt(fill_image, rect.x(), rect.y(), g_mask_images.l_width, | 554 canvas->TileImageInt(fill_image, rect.x(), rect.y(), g_mask_images.l_width, |
486 tab_insets.top(), rect.width(), rect.height()); | 555 tab_insets.top(), rect.width(), rect.height()); |
487 } | 556 } |
488 | 557 |
489 void PaintTabBackgroundUsingParams(gfx::Canvas* fill_canvas, | 558 // In non-MD mode, there is never a need to draw fill and stroke onto separate |
490 gfx::Canvas* stroke_canvas, | 559 // canvases, so in that case, this function does both. |
491 views::GlowHoverController* hc, | 560 void PaintTabFillUsingParams(gfx::Canvas* canvas, |
492 const PaintBackgroundParams& params) { | 561 const PaintBackgroundParams& params) { |
493 const gfx::Rect& rect = params.rect; | 562 const gfx::Rect& rect = params.rect; |
494 const SkScalar kMinHoverRadius = 16; | 563 const SkScalar kMinHoverRadius = 16; |
495 const SkScalar radius = | 564 const SkScalar radius = |
496 std::max(SkFloatToScalar(rect.width() / 4.f), kMinHoverRadius); | 565 std::max(SkFloatToScalar(rect.width() / 4.f), kMinHoverRadius); |
497 const bool draw_hover = !params.is_active && hc; | |
498 SkPoint hover_location( | |
499 gfx::PointToSkPoint(draw_hover ? hc->location() : gfx::Point())); | |
500 const SkColor hover_color = | 566 const SkColor hover_color = |
501 SkColorSetA(params.toolbar_color, draw_hover ? hc->GetAlpha() : 255); | 567 SkColorSetA(params.toolbar_color, params.hover_alpha); |
502 | 568 |
503 if (ui::MaterialDesignController::IsModeMaterial()) { | 569 if (ui::MaterialDesignController::IsModeMaterial()) { |
504 gfx::Path fill; | 570 gfx::ScopedCanvas scoped_canvas(canvas); |
505 SkPaint paint; | 571 const float scale = canvas->UndoDeviceScaleFactor(); |
506 paint.setAntiAlias(true); | 572 gfx::Path fill = GetFillPath(scale, rect.size()); |
507 | 573 |
508 // Draw the fill. | |
509 { | 574 { |
510 gfx::ScopedCanvas scoped_canvas(fill_canvas); | 575 gfx::ScopedCanvas clip_scoper(canvas); |
511 const float scale = fill_canvas->UndoDeviceScaleFactor(); | 576 canvas->ClipPath(fill, true); |
512 | 577 if (!params.fill_image.isNull()) { |
513 fill = GetFillPath(scale, rect.size()); | 578 gfx::ScopedCanvas scale_scoper(canvas); |
514 { | 579 canvas->sk_canvas()->scale(scale, scale); |
515 gfx::ScopedCanvas clip_scoper(fill_canvas); | 580 canvas->TileImageInt(params.fill_image, rect.x(), rect.y(), 0, 0, |
516 fill_canvas->ClipPath(fill, true); | 581 rect.width(), rect.height()); |
517 if (!params.fill_image.isNull()) { | 582 } else { |
518 gfx::ScopedCanvas scale_scoper(fill_canvas); | 583 SkPaint paint; |
519 fill_canvas->sk_canvas()->scale(scale, scale); | 584 paint.setAntiAlias(true); |
520 fill_canvas->TileImageInt(params.fill_image, rect.x(), rect.y(), 0, 0, | 585 paint.setColor(params.is_active ? params.toolbar_color |
521 rect.width(), rect.height()); | 586 : params.background_tab_color); |
522 } else { | 587 canvas->DrawRect( |
523 paint.setColor(params.is_active ? params.toolbar_color | 588 gfx::ScaleToEnclosingRect(gfx::Rect(rect.size()), scale), paint); |
524 : params.background_tab_color); | 589 } |
525 fill_canvas->DrawRect( | 590 if (params.draw_hover) { |
526 gfx::ScaleToEnclosingRect(gfx::Rect(rect.size()), scale), | 591 DrawHighlight(canvas, params.hover_location * scale, radius * scale, |
527 paint); | 592 hover_color); |
528 } | |
529 if (draw_hover) { | |
530 hover_location.scale(SkFloatToScalar(scale)); | |
531 DrawHighlight(fill_canvas, hover_location, radius * scale, | |
532 hover_color); | |
533 } | |
534 } | 593 } |
535 } | 594 } |
536 | |
537 // Draw the stroke. | |
538 { | |
539 gfx::ScopedCanvas scoped_canvas(stroke_canvas); | |
540 const float scale = stroke_canvas->UndoDeviceScaleFactor(); | |
541 | |
542 gfx::Path stroke = GetBorderPath(scale, false, false, rect.size()); | |
543 Op(stroke, fill, kDifference_SkPathOp, &stroke); | |
544 if (!params.is_active) { | |
545 // Clip out the bottom line; this will be drawn for us by | |
546 // TabStrip::PaintChildren(). | |
547 stroke_canvas->ClipRect(gfx::RectF(rect.width() * scale, | |
548 rect.height() * scale - 1)); | |
549 } | |
550 paint.setColor(params.stroke_color); | |
551 stroke_canvas->DrawPath(stroke, paint); | |
552 } | |
553 } else { | 595 } else { |
554 gfx::Canvas* canvas = stroke_canvas; | 596 if (params.draw_hover) { |
555 if (draw_hover) { | |
556 // Draw everything to a temporary canvas so we can extract an image for | 597 // Draw everything to a temporary canvas so we can extract an image for |
557 // use in masking the hover glow. | 598 // use in masking the hover glow. |
558 gfx::Canvas background_canvas(rect.size(), canvas->image_scale(), false); | 599 gfx::Canvas background_canvas(rect.size(), canvas->image_scale(), false); |
559 PaintTabFill(&background_canvas, params.fill_image, rect, | 600 PaintTabFill(&background_canvas, params.fill_image, rect, |
560 params.is_active); | 601 params.is_active); |
561 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); | 602 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); |
562 canvas->DrawImageInt(background_image, 0, 0); | 603 canvas->DrawImageInt(background_image, 0, 0); |
563 | 604 |
564 gfx::Canvas hover_canvas(rect.size(), canvas->image_scale(), false); | 605 gfx::Canvas hover_canvas(rect.size(), canvas->image_scale(), false); |
565 DrawHighlight(&hover_canvas, hover_location, radius, hover_color); | 606 DrawHighlight(&hover_canvas, params.hover_location, radius, hover_color); |
566 gfx::ImageSkia result = gfx::ImageSkiaOperations::CreateMaskedImage( | 607 gfx::ImageSkia result = gfx::ImageSkiaOperations::CreateMaskedImage( |
567 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); | 608 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); |
568 canvas->DrawImageInt(result, 0, 0); | 609 canvas->DrawImageInt(result, 0, 0); |
569 } else { | 610 } else { |
570 PaintTabFill(canvas, params.fill_image, rect, params.is_active); | 611 PaintTabFill(canvas, params.fill_image, rect, params.is_active); |
571 } | 612 } |
572 | 613 |
573 // Now draw the stroke, highlights, and shadows around the tab edge. | 614 // Now draw the stroke, highlights, and shadows around the tab edge. |
574 TabImages* stroke_images = | 615 TabImages* stroke_images = |
575 params.is_active ? &g_active_images : &g_inactive_images; | 616 params.is_active ? &g_active_images : &g_inactive_images; |
576 canvas->DrawImageInt(*stroke_images->image_l, 0, 0); | 617 canvas->DrawImageInt(*stroke_images->image_l, 0, 0); |
577 canvas->TileImageInt( | 618 canvas->TileImageInt( |
578 *stroke_images->image_c, stroke_images->l_width, 0, | 619 *stroke_images->image_c, stroke_images->l_width, 0, |
579 rect.width() - stroke_images->l_width - stroke_images->r_width, | 620 rect.width() - stroke_images->l_width - stroke_images->r_width, |
580 rect.height()); | 621 rect.height()); |
581 canvas->DrawImageInt(*stroke_images->image_r, | 622 canvas->DrawImageInt(*stroke_images->image_r, |
582 rect.width() - stroke_images->r_width, 0); | 623 rect.width() - stroke_images->r_width, 0); |
583 } | 624 } |
584 } | 625 } |
585 | 626 |
| 627 void PaintTabStrokeUsingParams(gfx::Canvas* canvas, |
| 628 const PaintBackgroundParams& params) { |
| 629 DCHECK(ui::MaterialDesignController::IsModeMaterial()); |
| 630 gfx::ScopedCanvas scoped_canvas(canvas); |
| 631 const float scale = canvas->UndoDeviceScaleFactor(); |
| 632 |
| 633 SkPaint paint; |
| 634 paint.setAntiAlias(true); |
| 635 gfx::Path stroke = GetBorderPath(scale, false, false, params.rect.size()); |
| 636 gfx::Path fill = GetFillPath(scale, params.rect.size()); |
| 637 Op(stroke, fill, kDifference_SkPathOp, &stroke); |
| 638 if (!params.is_active) { |
| 639 // Clip out the bottom line; this will be drawn for us by |
| 640 // TabStrip::PaintChildren(). |
| 641 canvas->ClipRect(gfx::RectF(params.rect.width() * scale, |
| 642 params.rect.height() * scale - 1)); |
| 643 } |
| 644 paint.setColor(params.stroke_color); |
| 645 canvas->DrawPath(stroke, paint); |
| 646 } |
| 647 |
586 // Desaturates the favicon. Should only be used for when a tab encounters a | 648 // Desaturates the favicon. Should only be used for when a tab encounters a |
587 // network error state. | 649 // network error state. |
588 void PaintDesaturatedFavIcon(gfx::Canvas* canvas, | 650 void PaintDesaturatedFavIcon(gfx::Canvas* canvas, |
589 gfx::ImageSkia& favicon, | 651 gfx::ImageSkia& favicon, |
590 const gfx::Rect& bounds) { | 652 const gfx::Rect& bounds) { |
591 color_utils::HSL shift = {kDesaturateHue, | 653 color_utils::HSL shift = {kDesaturateHue, |
592 kDesaturateSaturation, | 654 kDesaturateSaturation, |
593 kDesaturateLightness}; | 655 kDesaturateLightness}; |
594 gfx::ImageSkia desaturated_favicon = | 656 gfx::ImageSkia desaturated_favicon = |
595 gfx::ImageSkiaOperations::CreateHSLShiftedImage(favicon, shift); | 657 gfx::ImageSkiaOperations::CreateHSLShiftedImage(favicon, shift); |
(...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1445 else | 1507 else |
1446 StopPulse(); | 1508 StopPulse(); |
1447 } | 1509 } |
1448 | 1510 |
1449 void Tab::PaintTab(gfx::Canvas* canvas, const gfx::Path& clip) { | 1511 void Tab::PaintTab(gfx::Canvas* canvas, const gfx::Path& clip) { |
1450 const int kActiveTabFillId = IDR_THEME_TOOLBAR; | 1512 const int kActiveTabFillId = IDR_THEME_TOOLBAR; |
1451 const bool has_custom_image = | 1513 const bool has_custom_image = |
1452 GetThemeProvider()->HasCustomImage(kActiveTabFillId); | 1514 GetThemeProvider()->HasCustomImage(kActiveTabFillId); |
1453 const int y_offset = -GetYInsetForActiveTabBackground(); | 1515 const int y_offset = -GetYInsetForActiveTabBackground(); |
1454 if (IsActive()) { | 1516 if (IsActive()) { |
1455 PaintTabBackgroundUsingFillId(canvas, canvas, true, kActiveTabFillId, | 1517 PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId, |
1456 has_custom_image, y_offset); | 1518 has_custom_image, y_offset); |
1457 } else { | 1519 } else { |
1458 PaintInactiveTabBackground(canvas, clip); | 1520 PaintInactiveTabBackground(canvas, clip); |
1459 | 1521 |
1460 const double throb_value = GetThrobValue(); | 1522 const double throb_value = GetThrobValue(); |
1461 if (throb_value > 0) { | 1523 if (throb_value > 0) { |
1462 canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff), | 1524 canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff), |
1463 GetLocalBounds()); | 1525 GetLocalBounds()); |
1464 PaintTabBackgroundUsingFillId(canvas, canvas, true, kActiveTabFillId, | 1526 PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId, |
1465 has_custom_image, y_offset); | 1527 has_custom_image, y_offset); |
1466 canvas->Restore(); | 1528 canvas->Restore(); |
1467 } | 1529 } |
1468 } | 1530 } |
1469 | 1531 |
1470 if (showing_icon_) | 1532 if (showing_icon_) |
1471 PaintIcon(canvas); | 1533 PaintIcon(canvas); |
1472 } | 1534 } |
1473 | 1535 |
1474 void Tab::PaintImmersiveTab(gfx::Canvas* canvas) { | 1536 void Tab::PaintImmersiveTab(gfx::Canvas* canvas) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1525 // image is a composited foreground + frame image. Note that if the theme is | 1587 // image is a composited foreground + frame image. Note that if the theme is |
1526 // only providing a custom frame image, |has_custom_image| will be true, but | 1588 // only providing a custom frame image, |has_custom_image| will be true, but |
1527 // we should use the |background_offset_| here. | 1589 // we should use the |background_offset_| here. |
1528 const ui::ThemeProvider* tp = GetThemeProvider(); | 1590 const ui::ThemeProvider* tp = GetThemeProvider(); |
1529 const int y_offset = tp->HasCustomImage(fill_id) ? | 1591 const int y_offset = tp->HasCustomImage(fill_id) ? |
1530 -GetLayoutConstant(TAB_TOP_EXCLUSION_HEIGHT) : background_offset_.y(); | 1592 -GetLayoutConstant(TAB_TOP_EXCLUSION_HEIGHT) : background_offset_.y(); |
1531 | 1593 |
1532 // We only cache the image when it's the default image and we're not hovered, | 1594 // We only cache the image when it's the default image and we're not hovered, |
1533 // to avoid caching a background image that isn't the same for all tabs. | 1595 // to avoid caching a background image that isn't the same for all tabs. |
1534 if (has_custom_image || hover_controller_.ShouldDraw()) { | 1596 if (has_custom_image || hover_controller_.ShouldDraw()) { |
1535 PaintTabBackgroundUsingFillId(canvas, canvas, false, fill_id, | 1597 PaintTabBackgroundUsingFillId(canvas, false, fill_id, has_custom_image, |
1536 has_custom_image, y_offset); | 1598 y_offset); |
1537 return; | 1599 return; |
1538 } | 1600 } |
1539 | 1601 |
1540 // For efficiency, we don't use separate fill and stroke images unless we | 1602 // For efficiency, we don't use separate fill and stroke images unless we |
1541 // really need to clip the stroke and not the fill (for stacked tabs). This | 1603 // really need to clip the stroke and not the fill (for stacked tabs). This |
1542 // saves memory and avoids an extra image draw at the cost of recalculating | 1604 // saves memory and avoids an extra image draw at the cost of recalculating |
1543 // the images when MaySetClip() toggles. | 1605 // the images when MaySetClip() toggles. |
1544 const bool use_fill_and_stroke_images = | 1606 const bool use_fill_and_stroke_images = |
1545 controller_->MaySetClip() && | 1607 controller_->MaySetClip() && |
1546 ui::MaterialDesignController::IsModeMaterial(); | 1608 ui::MaterialDesignController::IsModeMaterial(); |
1547 | 1609 |
1548 const ImageCacheEntryMetadata metadata( | 1610 const ImageCacheEntryMetadata metadata( |
1549 fill_id, tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB), | 1611 fill_id, tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB), |
1550 controller_->GetToolbarTopSeparatorColor(), use_fill_and_stroke_images, | 1612 controller_->GetToolbarTopSeparatorColor(), use_fill_and_stroke_images, |
1551 ui::GetSupportedScaleFactor(canvas->image_scale()), size()); | 1613 size()); |
1552 auto it = std::find_if( | 1614 auto it = std::find_if( |
1553 g_image_cache->begin(), g_image_cache->end(), | 1615 g_image_cache->begin(), g_image_cache->end(), |
1554 [&metadata](const ImageCacheEntry& e) { return e.metadata == metadata; }); | 1616 [&metadata](const ImageCacheEntry& e) { return e.metadata == metadata; }); |
1555 if (it == g_image_cache->end()) { | 1617 if (it == g_image_cache->end()) { |
1556 gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false); | 1618 g_image_cache->emplace_front(metadata, this, fill_id, y_offset); |
1557 if (use_fill_and_stroke_images) { | |
1558 gfx::Canvas tmp_fill_canvas(size(), canvas->image_scale(), false); | |
1559 PaintTabBackgroundUsingFillId(&tmp_fill_canvas, &tmp_canvas, false, | |
1560 fill_id, false, y_offset); | |
1561 g_image_cache->emplace_front( | |
1562 metadata, gfx::ImageSkia(tmp_fill_canvas.ExtractImageRep()), | |
1563 gfx::ImageSkia(tmp_canvas.ExtractImageRep())); | |
1564 } else { | |
1565 PaintTabBackgroundUsingFillId(&tmp_canvas, &tmp_canvas, false, fill_id, | |
1566 false, y_offset); | |
1567 g_image_cache->emplace_front( | |
1568 metadata, gfx::ImageSkia(), | |
1569 gfx::ImageSkia(tmp_canvas.ExtractImageRep())); | |
1570 } | |
1571 if (g_image_cache->size() > kMaxImageCacheSize) | 1619 if (g_image_cache->size() > kMaxImageCacheSize) |
1572 g_image_cache->pop_back(); | 1620 g_image_cache->pop_back(); |
1573 it = g_image_cache->begin(); | 1621 it = g_image_cache->begin(); |
1574 } | 1622 } |
1575 | 1623 |
1576 gfx::ScopedCanvas scoped_canvas( | 1624 gfx::ScopedCanvas scoped_canvas( |
1577 use_fill_and_stroke_images ? canvas : nullptr); | 1625 use_fill_and_stroke_images ? canvas : nullptr); |
1578 if (use_fill_and_stroke_images) { | 1626 if (use_fill_and_stroke_images) { |
1579 canvas->DrawImageInt(it->fill_image, 0, 0); | 1627 canvas->DrawImageInt(it->fill_image, 0, 0); |
1580 canvas->sk_canvas()->clipPath(clip, SkRegion::kDifference_Op, true); | 1628 canvas->sk_canvas()->clipPath(clip, SkRegion::kDifference_Op, true); |
1581 } | 1629 } |
1582 canvas->DrawImageInt(it->stroke_image, 0, 0); | 1630 canvas->DrawImageInt(it->stroke_image, 0, 0); |
1583 } | 1631 } |
1584 | 1632 |
1585 void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* fill_canvas, | 1633 void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* canvas, |
1586 gfx::Canvas* stroke_canvas, | |
1587 bool is_active, | 1634 bool is_active, |
1588 int fill_id, | 1635 int fill_id, |
1589 bool has_custom_image, | 1636 bool has_custom_image, |
1590 int y_offset) { | 1637 int y_offset) { |
1591 views::GlowHoverController* hc = | |
1592 hover_controller_.ShouldDraw() ? &hover_controller_ : nullptr; | |
1593 gfx::ImageSkia* fill_image = | 1638 gfx::ImageSkia* fill_image = |
1594 has_custom_image || !ui::MaterialDesignController::IsModeMaterial() | 1639 has_custom_image || !ui::MaterialDesignController::IsModeMaterial() |
1595 ? GetThemeProvider()->GetImageSkiaNamed(fill_id) | 1640 ? GetThemeProvider()->GetImageSkiaNamed(fill_id) |
1596 : nullptr; | 1641 : nullptr; |
1597 // The tab image needs to be lined up with the background image | 1642 // The tab image needs to be lined up with the background image |
1598 // so that it feels partially transparent. These offsets represent the tab | 1643 // so that it feels partially transparent. These offsets represent the tab |
1599 // position within the frame background image. | 1644 // position within the frame background image. |
1600 gfx::Rect rect(GetLocalBounds()); | 1645 gfx::Rect rect(GetLocalBounds()); |
1601 rect.Offset(GetMirroredX() + background_offset_.x(), y_offset); | 1646 rect.Offset(GetMirroredX() + background_offset_.x(), y_offset); |
1602 PaintBackgroundParams params( | 1647 PaintBackgroundParams params( |
1603 is_active, fill_image, has_custom_image, rect, | 1648 is_active, fill_image, has_custom_image, rect, |
1604 controller_->GetToolbarTopSeparatorColor(), | 1649 controller_->GetToolbarTopSeparatorColor(), |
1605 GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR), | 1650 GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR), |
1606 GetThemeProvider()->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB)); | 1651 GetThemeProvider()->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB), |
| 1652 !is_active && hover_controller_.ShouldDraw(), |
| 1653 hover_controller_.location(), hover_controller_.GetAlpha()); |
1607 | 1654 |
1608 PaintTabBackgroundUsingParams(fill_canvas, stroke_canvas, hc, params); | 1655 PaintTabFillUsingParams(canvas, params); |
| 1656 PaintTabStrokeUsingParams(canvas, params); |
1609 } | 1657 } |
1610 | 1658 |
1611 void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( | 1659 void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( |
1612 gfx::Canvas* canvas, | 1660 gfx::Canvas* canvas, |
1613 const gfx::Rect& favicon_draw_bounds) { | 1661 const gfx::Rect& favicon_draw_bounds) { |
1614 // The pinned tab title changed indicator consists of two parts: | 1662 // The pinned tab title changed indicator consists of two parts: |
1615 // . a clear (totally transparent) part over the bottom right (or left in rtl) | 1663 // . a clear (totally transparent) part over the bottom right (or left in rtl) |
1616 // of the favicon. This is done by drawing the favicon to a canvas, then | 1664 // of the favicon. This is done by drawing the favicon to a canvas, then |
1617 // drawing the clear part on top of the favicon. | 1665 // drawing the clear part on top of the favicon. |
1618 // . a circle in the bottom right (or left in rtl) of the favicon. | 1666 // . a circle in the bottom right (or left in rtl) of the favicon. |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1859 gfx::Rect Tab::GetImmersiveBarRect() const { | 1907 gfx::Rect Tab::GetImmersiveBarRect() const { |
1860 // The main bar is as wide as the normal tab's horizontal top line. | 1908 // The main bar is as wide as the normal tab's horizontal top line. |
1861 // This top line of the tab extends a few pixels left and right of the | 1909 // This top line of the tab extends a few pixels left and right of the |
1862 // center image due to pixels in the rounded corner images. | 1910 // center image due to pixels in the rounded corner images. |
1863 const int kBarPadding = 1; | 1911 const int kBarPadding = 1; |
1864 int main_bar_left = g_active_images.l_width - kBarPadding; | 1912 int main_bar_left = g_active_images.l_width - kBarPadding; |
1865 int main_bar_right = width() - g_active_images.r_width + kBarPadding; | 1913 int main_bar_right = width() - g_active_images.r_width + kBarPadding; |
1866 return gfx::Rect( | 1914 return gfx::Rect( |
1867 main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight); | 1915 main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight); |
1868 } | 1916 } |
OLD | NEW |