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 |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/debug/alias.h" | 12 #include "base/debug/alias.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/metrics/user_metrics.h" | 14 #include "base/metrics/user_metrics.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 17 #include "cc/paint/paint_shader.h" | 17 #include "cc/paint/paint_flags.h" |
| 18 #include "chrome/app/vector_icons/vector_icons.h" | 18 #include "chrome/app/vector_icons/vector_icons.h" |
| 19 #include "chrome/browser/themes/theme_properties.h" | 19 #include "chrome/browser/themes/theme_properties.h" |
| 20 #include "chrome/browser/ui/browser.h" | 20 #include "chrome/browser/ui/browser.h" |
| 21 #include "chrome/browser/ui/layout_constants.h" | 21 #include "chrome/browser/ui/layout_constants.h" |
| 22 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" | 22 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" |
| 23 #include "chrome/browser/ui/tabs/tab_utils.h" | 23 #include "chrome/browser/ui/tabs/tab_utils.h" |
| 24 #include "chrome/browser/ui/view_ids.h" | 24 #include "chrome/browser/ui/view_ids.h" |
| 25 #include "chrome/browser/ui/views/frame/browser_view.h" | 25 #include "chrome/browser/ui/views/frame/browser_view.h" |
| 26 #include "chrome/browser/ui/views/tabs/alert_indicator_button.h" | 26 #include "chrome/browser/ui/views/tabs/alert_indicator_button.h" |
| 27 #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" | 27 #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 | 86 |
| 87 // How opaque to make the hover state (out of 1). | 87 // How opaque to make the hover state (out of 1). |
| 88 const double kHoverOpacity = 0.33; | 88 const double kHoverOpacity = 0.33; |
| 89 | 89 |
| 90 // Opacity of the active tab background painted over inactive selected tabs. | 90 // Opacity of the active tab background painted over inactive selected tabs. |
| 91 const double kSelectedTabOpacity = 0.3; | 91 const double kSelectedTabOpacity = 0.3; |
| 92 | 92 |
| 93 // Inactive selected tabs have their throb value scaled by this. | 93 // Inactive selected tabs have their throb value scaled by this. |
| 94 const double kSelectedTabThrobScale = 0.95 - kSelectedTabOpacity; | 94 const double kSelectedTabThrobScale = 0.95 - kSelectedTabOpacity; |
| 95 | 95 |
| 96 // Max number of images to cache. This has to be at least two since rounding | |
| 97 // errors may lead to tabs in the same tabstrip having different sizes. | |
| 98 // 8 = normal/incognito, active/inactive, 2 sizes within tabstrip. | |
| 99 const size_t kMaxImageCacheSize = 8; | |
| 100 | |
| 101 const char kTabCloseButtonName[] = "TabCloseButton"; | 96 const char kTabCloseButtonName[] = "TabCloseButton"; |
| 102 | 97 |
| 103 //////////////////////////////////////////////////////////////////////////////// | 98 //////////////////////////////////////////////////////////////////////////////// |
| 104 // ImageCacheEntryMetadata | |
| 105 // | |
| 106 // All metadata necessary to uniquely identify a cached image. | |
| 107 struct ImageCacheEntryMetadata { | |
| 108 ImageCacheEntryMetadata(SkColor fill_color, | |
| 109 SkColor stroke_color, | |
| 110 bool use_fill_and_stroke_images, | |
| 111 float scale_factor, | |
| 112 const gfx::Size& size); | |
| 113 | |
| 114 ~ImageCacheEntryMetadata(); | |
| 115 | |
| 116 bool operator==(const ImageCacheEntryMetadata& rhs) const; | |
| 117 | |
| 118 SkColor fill_color; | |
| 119 SkColor stroke_color; | |
| 120 bool use_fill_and_stroke_images; | |
| 121 float scale_factor; | |
| 122 gfx::Size size; | |
| 123 }; | |
| 124 | |
| 125 ImageCacheEntryMetadata::ImageCacheEntryMetadata( | |
| 126 SkColor fill_color, | |
| 127 SkColor stroke_color, | |
| 128 bool use_fill_and_stroke_images, | |
| 129 float scale_factor, | |
| 130 const gfx::Size& size) | |
| 131 : fill_color(fill_color), | |
| 132 stroke_color(stroke_color), | |
| 133 use_fill_and_stroke_images(use_fill_and_stroke_images), | |
| 134 scale_factor(scale_factor), | |
| 135 size(size) {} | |
| 136 | |
| 137 ImageCacheEntryMetadata::~ImageCacheEntryMetadata() {} | |
| 138 | |
| 139 bool ImageCacheEntryMetadata::operator==( | |
| 140 const ImageCacheEntryMetadata& rhs) const { | |
| 141 return fill_color == rhs.fill_color && stroke_color == rhs.stroke_color && | |
| 142 use_fill_and_stroke_images == rhs.use_fill_and_stroke_images && | |
| 143 scale_factor == rhs.scale_factor && size == rhs.size; | |
| 144 } | |
| 145 | |
| 146 //////////////////////////////////////////////////////////////////////////////// | |
| 147 // ImageCacheEntry and cache management | |
| 148 // | |
| 149 // A cached image and the metadata used to generate it. | |
| 150 struct ImageCacheEntry { | |
| 151 ImageCacheEntry(const ImageCacheEntryMetadata& metadata, | |
| 152 const gfx::ImageSkia& fill_image, | |
| 153 const gfx::ImageSkia& stroke_image); | |
| 154 ~ImageCacheEntry(); | |
| 155 | |
| 156 ImageCacheEntryMetadata metadata; | |
| 157 gfx::ImageSkia fill_image; | |
| 158 gfx::ImageSkia stroke_image; | |
| 159 }; | |
| 160 | |
| 161 ImageCacheEntry::ImageCacheEntry(const ImageCacheEntryMetadata& metadata, | |
| 162 const gfx::ImageSkia& fill_image, | |
| 163 const gfx::ImageSkia& stroke_image) | |
| 164 : metadata(metadata), fill_image(fill_image), stroke_image(stroke_image) {} | |
| 165 | |
| 166 ImageCacheEntry::~ImageCacheEntry() {} | |
| 167 | |
| 168 typedef std::list<ImageCacheEntry> ImageCache; | |
| 169 | |
| 170 // As the majority of the tabs are inactive, and painting tabs is slowish, | |
| 171 // we cache a handful of the inactive tab backgrounds here. | |
| 172 static ImageCache* g_image_cache = nullptr; | |
| 173 | |
| 174 // Performs a one-time initialization of static resources such as tab images. | |
| 175 void InitTabResources() { | |
| 176 static bool initialized = false; | |
| 177 if (initialized) | |
| 178 return; | |
| 179 | |
| 180 initialized = true; | |
| 181 g_image_cache = new ImageCache(); | |
| 182 } | |
| 183 | |
| 184 //////////////////////////////////////////////////////////////////////////////// | |
| 185 // Drawing and utility functions | 99 // Drawing and utility functions |
| 186 | 100 |
| 187 // Returns the width of the tab endcap at scale 1. More precisely, this is the | 101 // Returns the width of the tab endcap at scale 1. More precisely, this is the |
| 188 // width of the curve making up either the outer or inner edge of the stroke; | 102 // width of the curve making up either the outer or inner edge of the stroke; |
| 189 // since these two curves are horizontally offset by 1 px (regardless of scale), | 103 // since these two curves are horizontally offset by 1 px (regardless of scale), |
| 190 // the total width of the endcap from tab outer edge to the inside end of the | 104 // the total width of the endcap from tab outer edge to the inside end of the |
| 191 // stroke inner edge is (GetUnscaledEndcapWidth() * scale) + 1. | 105 // stroke inner edge is (GetUnscaledEndcapWidth() * scale) + 1. |
| 192 float GetUnscaledEndcapWidth() { | 106 float GetUnscaledEndcapWidth() { |
| 193 return GetLayoutInsets(TAB).left() - 0.5f; | 107 return GetLayoutInsets(TAB).left() - 0.5f; |
| 194 } | 108 } |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 527 alert_indicator_button_(nullptr), | 441 alert_indicator_button_(nullptr), |
| 528 close_button_(nullptr), | 442 close_button_(nullptr), |
| 529 title_(new views::Label()), | 443 title_(new views::Label()), |
| 530 tab_activated_with_last_tap_down_(false), | 444 tab_activated_with_last_tap_down_(false), |
| 531 hover_controller_(this), | 445 hover_controller_(this), |
| 532 showing_icon_(false), | 446 showing_icon_(false), |
| 533 showing_alert_indicator_(false), | 447 showing_alert_indicator_(false), |
| 534 showing_close_button_(false), | 448 showing_close_button_(false), |
| 535 button_color_(SK_ColorTRANSPARENT) { | 449 button_color_(SK_ColorTRANSPARENT) { |
| 536 DCHECK(controller); | 450 DCHECK(controller); |
| 537 InitTabResources(); | |
| 538 | 451 |
| 539 // So we get don't get enter/exit on children and don't prematurely stop the | 452 // So we get don't get enter/exit on children and don't prematurely stop the |
| 540 // hover. | 453 // hover. |
| 541 set_notify_enter_exit_on_child(true); | 454 set_notify_enter_exit_on_child(true); |
| 542 | 455 |
| 543 set_id(VIEW_ID_TAB); | 456 set_id(VIEW_ID_TAB); |
| 544 | 457 |
| 545 SetBorder(views::CreateEmptyBorder(GetLayoutInsets(TAB))); | 458 SetBorder(views::CreateEmptyBorder(GetLayoutInsets(TAB))); |
| 546 | 459 |
| 547 title_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); | 460 title_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); |
| (...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1111 if (data().blocked == old.blocked) | 1024 if (data().blocked == old.blocked) |
| 1112 return; | 1025 return; |
| 1113 | 1026 |
| 1114 if (data().blocked) | 1027 if (data().blocked) |
| 1115 StartPulse(); | 1028 StartPulse(); |
| 1116 else | 1029 else |
| 1117 StopPulse(); | 1030 StopPulse(); |
| 1118 } | 1031 } |
| 1119 | 1032 |
| 1120 void Tab::PaintTab(gfx::Canvas* canvas, const gfx::Path& clip) { | 1033 void Tab::PaintTab(gfx::Canvas* canvas, const gfx::Path& clip) { |
| 1121 const int kActiveTabFillId = | 1034 const int kActiveTabFillId = |
|
danakj
2017/04/07 19:10:49
btw while we're pointing at naming, these should n
| |
| 1122 GetThemeProvider()->HasCustomImage(IDR_THEME_TOOLBAR) ? IDR_THEME_TOOLBAR | 1035 GetThemeProvider()->HasCustomImage(IDR_THEME_TOOLBAR) ? IDR_THEME_TOOLBAR |
| 1123 : 0; | 1036 : 0; |
| 1124 const int y_offset = -GetLayoutInsets(TAB).top(); | 1037 const int y_offset = -GetLayoutInsets(TAB).top(); |
| 1125 if (IsActive()) { | 1038 if (IsActive()) { |
| 1126 PaintTabBackgroundUsingFillId(canvas, canvas, true, kActiveTabFillId, | 1039 bool active = true; |
| 1127 y_offset); | 1040 gfx::Path* no_clip = nullptr; |
|
Peter Kasting
2017/04/06 00:52:11
Nit: Please don't pull this kind of thing out. It
danakj
2017/04/06 17:05:28
If I didn't give it a name this way I'd want to wr
Peter Kasting
2017/04/06 18:49:44
don't love it enough to do it myself, but I don't
danakj
2017/04/07 19:10:49
Sure, I think that's nicer than inline comments. I
| |
| 1041 PaintTabBackground(canvas, active, kActiveTabFillId, y_offset, no_clip); | |
| 1128 } else { | 1042 } else { |
| 1129 PaintInactiveTabBackground(canvas, clip); | 1043 PaintInactiveTabBackground(canvas, clip); |
| 1130 | 1044 |
| 1131 const double throb_value = GetThrobValue(); | 1045 const double throb_value = GetThrobValue(); |
| 1132 if (throb_value > 0) { | 1046 if (throb_value > 0) { |
| 1133 canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff), | 1047 canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff), |
| 1134 GetLocalBounds()); | 1048 GetLocalBounds()); |
| 1135 PaintTabBackgroundUsingFillId(canvas, canvas, true, kActiveTabFillId, | 1049 bool active = true; |
| 1136 y_offset); | 1050 gfx::Path* no_clip = nullptr; |
| 1051 PaintTabBackground(canvas, active, kActiveTabFillId, y_offset, no_clip); | |
| 1137 canvas->Restore(); | 1052 canvas->Restore(); |
| 1138 } | 1053 } |
| 1139 } | 1054 } |
| 1140 | 1055 |
| 1141 if (showing_icon_) | 1056 if (showing_icon_) |
| 1142 PaintIcon(canvas); | 1057 PaintIcon(canvas); |
| 1143 } | 1058 } |
| 1144 | 1059 |
| 1145 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas, | 1060 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas, |
| 1146 const gfx::Path& clip) { | 1061 const gfx::Path& clip) { |
| 1147 bool has_custom_image; | 1062 bool has_custom_image; |
| 1148 int fill_id = controller_->GetBackgroundResourceId(&has_custom_image); | 1063 int background_resource_id = |
| 1149 const ui::ThemeProvider* tp = GetThemeProvider(); | 1064 controller_->GetBackgroundResourceId(&has_custom_image); |
| 1150 | 1065 |
| 1151 // We only cache the image when it's the default image and we're not hovered, | 1066 int fill_id = 0; |
| 1152 // to avoid caching a background image that isn't the same for all tabs. | 1067 int y_offset = 0; |
| 1068 bool may_clip = controller_->MaySetClip(); | |
| 1069 | |
| 1153 if (has_custom_image) { | 1070 if (has_custom_image) { |
| 1071 const ui::ThemeProvider* tp = GetThemeProvider(); | |
| 1072 | |
| 1154 // If the theme is providing a custom background image, then its top edge | 1073 // If the theme is providing a custom background image, then its top edge |
| 1155 // should be at the top of the tab. Otherwise, we assume that the background | 1074 // should be at the top of the tab. Otherwise, we assume that the background |
| 1156 // image is a composited foreground + frame image. Note that if the theme | 1075 // image is a composited foreground + frame image. Note that if the theme |
| 1157 // is only providing a custom frame image, |has_custom_image| will be true, | 1076 // is only providing a custom frame image, |has_custom_image| will be true, |
| 1158 // but we should use the |background_offset_| here. | 1077 // but we should use the |background_offset_| here. |
| 1159 const int y_offset = | 1078 fill_id = background_resource_id; |
| 1160 tp->HasCustomImage(fill_id) ? 0 : background_offset_.y(); | 1079 y_offset = |
| 1161 PaintTabBackgroundUsingFillId(canvas, canvas, false, fill_id, y_offset); | 1080 tp->HasCustomImage(background_resource_id) ? 0 : background_offset_.y(); |
| 1162 return; | 1081 may_clip = false; |
| 1163 } | |
| 1164 if (hover_controller_.ShouldDraw()) { | |
| 1165 PaintTabBackgroundUsingFillId(canvas, canvas, false, 0, 0); | |
| 1166 return; | |
| 1167 } | 1082 } |
| 1168 | 1083 |
| 1169 // For efficiency, we don't use separate fill and stroke images unless we | 1084 bool active = false; |
| 1170 // really need to clip the stroke and not the fill (for stacked tabs). This | 1085 PaintTabBackground(canvas, active, fill_id, y_offset, |
| 1171 // saves memory and avoids an extra image draw at the cost of recalculating | 1086 may_clip ? &clip : nullptr); |
|
Peter Kasting
2017/04/06 00:52:11
Nit: All the temps have made this function hard fo
danakj
2017/04/06 17:05:28
I really liked not splitting this into multiple ca
Peter Kasting
2017/04/06 18:49:44
After suggesting rewriting yesterday, I asked myse
danakj
2017/04/07 19:10:49
Done. Also observing that we always now clip inact
Peter Kasting
2017/04/07 23:34:02
Correct; the active tab should always be frontmost
| |
| 1172 // the images when MaySetClip() toggles. | |
| 1173 const bool use_fill_and_stroke_images = controller_->MaySetClip(); | |
| 1174 | |
| 1175 const ImageCacheEntryMetadata metadata( | |
| 1176 tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB), | |
| 1177 controller_->GetToolbarTopSeparatorColor(), use_fill_and_stroke_images, | |
| 1178 canvas->image_scale(), size()); | |
| 1179 auto it = std::find_if( | |
| 1180 g_image_cache->begin(), g_image_cache->end(), | |
| 1181 [&metadata](const ImageCacheEntry& e) { return e.metadata == metadata; }); | |
| 1182 if (it == g_image_cache->end()) { | |
| 1183 gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false); | |
| 1184 if (use_fill_and_stroke_images) { | |
| 1185 gfx::Canvas tmp_fill_canvas(size(), canvas->image_scale(), false); | |
| 1186 PaintTabBackgroundUsingFillId(&tmp_fill_canvas, &tmp_canvas, false, 0, 0); | |
| 1187 g_image_cache->emplace_front( | |
| 1188 metadata, gfx::ImageSkia(tmp_fill_canvas.ExtractImageRep()), | |
| 1189 gfx::ImageSkia(tmp_canvas.ExtractImageRep())); | |
| 1190 } else { | |
| 1191 PaintTabBackgroundUsingFillId(&tmp_canvas, &tmp_canvas, false, 0, 0); | |
| 1192 g_image_cache->emplace_front( | |
| 1193 metadata, gfx::ImageSkia(), | |
| 1194 gfx::ImageSkia(tmp_canvas.ExtractImageRep())); | |
| 1195 } | |
| 1196 if (g_image_cache->size() > kMaxImageCacheSize) | |
| 1197 g_image_cache->pop_back(); | |
| 1198 it = g_image_cache->begin(); | |
| 1199 } | |
| 1200 | |
| 1201 gfx::ScopedCanvas scoped_canvas( | |
| 1202 use_fill_and_stroke_images ? canvas : nullptr); | |
| 1203 if (use_fill_and_stroke_images) { | |
| 1204 canvas->DrawImageInt(it->fill_image, 0, 0); | |
| 1205 canvas->sk_canvas()->clipPath(clip, SkClipOp::kDifference, true); | |
| 1206 } | |
| 1207 canvas->DrawImageInt(it->stroke_image, 0, 0); | |
| 1208 } | 1087 } |
| 1209 | 1088 |
| 1210 void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* fill_canvas, | 1089 void Tab::PaintTabBackground(gfx::Canvas* canvas, |
| 1211 gfx::Canvas* stroke_canvas, | 1090 bool active, |
| 1212 bool is_active, | 1091 int fill_id, |
| 1213 int fill_id, | 1092 int y_offset, |
| 1214 int y_offset) { | 1093 const gfx::Path* clip) { |
| 1215 gfx::Path fill; | 1094 gfx::Path fill_path = GetFillPath(canvas->image_scale(), size()); |
| 1216 cc::PaintFlags flags; | |
| 1217 flags.setAntiAlias(true); | |
| 1218 | 1095 |
| 1219 // Draw the fill. | 1096 PaintTabBackgroundFill(canvas, fill_path, active, fill_id, y_offset); |
| 1220 { | 1097 { |
| 1221 gfx::ScopedCanvas scoped_canvas(fill_canvas); | 1098 base::Optional<gfx::ScopedCanvas> scoped_canvas; |
|
Peter Kasting
2017/04/06 00:52:11
Nit: It seems like it would be marginally simpler
danakj
2017/04/06 17:05:28
Ya that's fair, if you can move, then we can init
| |
| 1222 const float scale = fill_canvas->UndoDeviceScaleFactor(); | 1099 if (clip) { |
| 1223 const ui::ThemeProvider* tp = GetThemeProvider(); | 1100 scoped_canvas.emplace(canvas); |
| 1224 const SkColor toolbar_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR); | 1101 canvas->sk_canvas()->clipPath(*clip, SkClipOp::kDifference, true); |
| 1225 | |
| 1226 fill = GetFillPath(scale, size()); | |
| 1227 { | |
| 1228 gfx::ScopedCanvas clip_scoper(fill_canvas); | |
| 1229 fill_canvas->ClipPath(fill, true); | |
| 1230 if (fill_id) { | |
| 1231 gfx::ScopedCanvas scale_scoper(fill_canvas); | |
| 1232 fill_canvas->sk_canvas()->scale(scale, scale); | |
| 1233 fill_canvas->TileImageInt(*tp->GetImageSkiaNamed(fill_id), | |
| 1234 GetMirroredX() + background_offset_.x(), | |
| 1235 y_offset, 0, 0, width(), height()); | |
| 1236 } else { | |
| 1237 flags.setColor( | |
| 1238 is_active ? toolbar_color | |
| 1239 : tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB)); | |
| 1240 fill_canvas->DrawRect( | |
| 1241 gfx::ScaleToEnclosingRect(GetLocalBounds(), scale), flags); | |
| 1242 } | |
| 1243 | |
| 1244 if (!is_active && hover_controller_.ShouldDraw()) { | |
| 1245 SkPoint hover_location( | |
| 1246 gfx::PointToSkPoint(hover_controller_.location())); | |
| 1247 hover_location.scale(SkFloatToScalar(scale)); | |
| 1248 const SkScalar kMinHoverRadius = 16; | |
| 1249 const SkScalar radius = | |
| 1250 std::max(SkFloatToScalar(width() / 4.f), kMinHoverRadius); | |
| 1251 DrawHighlight(fill_canvas, hover_location, radius * scale, | |
| 1252 SkColorSetA(toolbar_color, hover_controller_.GetAlpha())); | |
| 1253 } | |
| 1254 } | 1102 } |
| 1255 } | 1103 PaintTabBackgroundStroke(canvas, fill_path, active); |
| 1256 | |
| 1257 // Draw the stroke. | |
| 1258 { | |
| 1259 gfx::ScopedCanvas scoped_canvas(stroke_canvas); | |
| 1260 const float scale = stroke_canvas->UndoDeviceScaleFactor(); | |
| 1261 | |
| 1262 gfx::Path stroke = GetBorderPath(scale, false, false, size()); | |
| 1263 Op(stroke, fill, kDifference_SkPathOp, &stroke); | |
| 1264 if (!is_active) { | |
| 1265 // Clip out the bottom line; this will be drawn for us by | |
| 1266 // TabStrip::PaintChildren(). | |
| 1267 stroke_canvas->ClipRect( | |
| 1268 gfx::RectF(width() * scale, height() * scale - 1)); | |
| 1269 } | |
| 1270 flags.setColor(controller_->GetToolbarTopSeparatorColor()); | |
| 1271 stroke_canvas->DrawPath(stroke, flags); | |
| 1272 } | 1104 } |
| 1273 } | 1105 } |
| 1274 | 1106 |
| 1107 void Tab::PaintTabBackgroundFill(gfx::Canvas* canvas, | |
| 1108 const gfx::Path& fill_path, | |
| 1109 bool active, | |
| 1110 int fill_id, | |
| 1111 int y_offset) { | |
| 1112 const ui::ThemeProvider* tp = GetThemeProvider(); | |
| 1113 SkColor active_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR); | |
| 1114 SkColor inactive_color = tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB); | |
| 1115 | |
| 1116 gfx::ScopedCanvas scoped_canvas(canvas); | |
| 1117 const float scale = canvas->UndoDeviceScaleFactor(); | |
| 1118 | |
| 1119 canvas->ClipPath(fill_path, true); | |
| 1120 if (fill_id) { | |
| 1121 gfx::ScopedCanvas scale_scoper(canvas); | |
| 1122 canvas->sk_canvas()->scale(scale, scale); | |
| 1123 canvas->TileImageInt(*tp->GetImageSkiaNamed(fill_id), | |
| 1124 GetMirroredX() + background_offset_.x(), y_offset, 0, | |
| 1125 0, width(), height()); | |
| 1126 } else { | |
| 1127 cc::PaintFlags flags; | |
| 1128 flags.setAntiAlias(true); | |
| 1129 flags.setColor(active ? active_color : inactive_color); | |
| 1130 canvas->DrawRect(gfx::ScaleToEnclosingRect(GetLocalBounds(), scale), flags); | |
| 1131 } | |
| 1132 | |
| 1133 if (!active && hover_controller_.ShouldDraw()) { | |
| 1134 SkPoint hover_location(gfx::PointToSkPoint(hover_controller_.location())); | |
| 1135 hover_location.scale(SkFloatToScalar(scale)); | |
| 1136 const SkScalar kMinHoverRadius = 16; | |
| 1137 const SkScalar radius = | |
| 1138 std::max(SkFloatToScalar(width() / 4.f), kMinHoverRadius); | |
| 1139 DrawHighlight(canvas, hover_location, radius * scale, | |
| 1140 SkColorSetA(active_color, hover_controller_.GetAlpha())); | |
| 1141 } | |
| 1142 } | |
| 1143 | |
| 1144 void Tab::PaintTabBackgroundStroke(gfx::Canvas* canvas, | |
| 1145 const gfx::Path& fill_path, | |
| 1146 bool active) { | |
| 1147 SkColor color = controller_->GetToolbarTopSeparatorColor(); | |
| 1148 | |
| 1149 gfx::ScopedCanvas scoped_canvas(canvas); | |
| 1150 const float scale = canvas->UndoDeviceScaleFactor(); | |
| 1151 | |
| 1152 gfx::Path stroke = GetBorderPath(scale, false, false, size()); | |
| 1153 Op(stroke, fill_path, kDifference_SkPathOp, &stroke); | |
| 1154 if (!active) { | |
| 1155 // Clip out the bottom line; this will be drawn for us by | |
| 1156 // TabStrip::PaintChildren(). | |
| 1157 canvas->ClipRect(gfx::RectF(width() * scale, height() * scale - 1)); | |
| 1158 } | |
| 1159 cc::PaintFlags flags; | |
| 1160 flags.setAntiAlias(true); | |
| 1161 flags.setColor(color); | |
| 1162 canvas->DrawPath(stroke, flags); | |
| 1163 } | |
| 1164 | |
| 1275 void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( | 1165 void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( |
| 1276 gfx::Canvas* canvas, | 1166 gfx::Canvas* canvas, |
| 1277 const gfx::Rect& favicon_draw_bounds) { | 1167 const gfx::Rect& favicon_draw_bounds) { |
| 1278 // The pinned tab title changed indicator consists of two parts: | 1168 // The pinned tab title changed indicator consists of two parts: |
| 1279 // . a clear (totally transparent) part over the bottom right (or left in rtl) | 1169 // . a clear (totally transparent) part over the bottom right (or left in rtl) |
| 1280 // of the favicon. This is done by drawing the favicon to a canvas, then | 1170 // of the favicon. This is done by drawing the favicon to a canvas, then |
| 1281 // drawing the clear part on top of the favicon. | 1171 // drawing the clear part on top of the favicon. |
| 1282 // . a circle in the bottom right (or left in rtl) of the favicon. | 1172 // . a circle in the bottom right (or left in rtl) of the favicon. |
| 1283 if (!favicon_.isNull()) { | 1173 if (!favicon_.isNull()) { |
| 1284 const float kIndicatorCropRadius = 4.5; | 1174 const float kIndicatorCropRadius = 4.5; |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1486 gfx::Rect bounds = favicon_bounds_; | 1376 gfx::Rect bounds = favicon_bounds_; |
| 1487 if (bounds.IsEmpty()) | 1377 if (bounds.IsEmpty()) |
| 1488 return; | 1378 return; |
| 1489 | 1379 |
| 1490 // Extends the area to the bottom when the crash animation is in progress. | 1380 // Extends the area to the bottom when the crash animation is in progress. |
| 1491 if (crash_icon_animation_->is_animating()) | 1381 if (crash_icon_animation_->is_animating()) |
| 1492 bounds.set_height(height() - bounds.y()); | 1382 bounds.set_height(height() - bounds.y()); |
| 1493 bounds.set_x(GetMirroredXForRect(bounds)); | 1383 bounds.set_x(GetMirroredXForRect(bounds)); |
| 1494 SchedulePaintInRect(bounds); | 1384 SchedulePaintInRect(bounds); |
| 1495 } | 1385 } |
| OLD | NEW |