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

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

Issue 2803583003: ui: Remove use of bitmaps when painting tab backgrounds. (Closed)
Patch Set: tabbackground: cache-paths Created 3 years, 8 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
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
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 17 matching lines...) Expand all
212 bool ShouldThemifyFaviconForUrl(const GURL& url) { 126 bool ShouldThemifyFaviconForUrl(const GURL& url) {
213 return url.SchemeIs(content::kChromeUIScheme) && 127 return url.SchemeIs(content::kChromeUIScheme) &&
214 url.host() != chrome::kChromeUIHelpHost && 128 url.host() != chrome::kChromeUIHelpHost &&
215 url.host() != chrome::kChromeUIUberHost && 129 url.host() != chrome::kChromeUIUberHost &&
216 url.host() != chrome::kChromeUIAppLauncherPageHost; 130 url.host() != chrome::kChromeUIAppLauncherPageHost;
217 } 131 }
218 132
219 // Returns a path corresponding to the tab's content region inside the outer 133 // Returns a path corresponding to the tab's content region inside the outer
220 // stroke. 134 // stroke.
221 gfx::Path GetFillPath(float scale, const gfx::Size& size) { 135 gfx::Path GetFillPath(float scale, const gfx::Size& size) {
136 struct FillPathCache {
137 // The parameters used to build the path.
138 float scale;
139 gfx::Size size;
140
141 // The constructed path based on the parameters.
142 gfx::Path path;
143 };
144 // A cache sorted from most recently used to least.
145 static auto& cache = *new std::list<FillPathCache>;
Peter Kasting 2017/04/06 18:49:45 Can we use a base::MRUCache instead of manually ro
danakj 2017/04/07 19:10:49 We could, I had looked there first, but it just lo
Peter Kasting 2017/04/07 23:34:02 Would it make sense to move MRUCache to one of the
146 static const int kCacheSize = 8;
Peter Kasting 2017/04/06 18:49:45 Nit: constexpr size_t
danakj 2017/04/07 19:10:49 Done.
147
148 // Find a match in the cache and move it to the front and return it.
149 for (auto it = cache.begin(); it != cache.end(); ++it) {
150 if (it->scale == scale && it->size == size) {
151 std::list<FillPathCache> hit;
152 hit.splice(hit.begin(), cache, it, std::next(it));
153 cache.splice(cache.begin(), std::move(hit));
Peter Kasting 2017/04/07 23:34:02 Can we just use std::rotate? This should work wit
danakj 2017/04/18 16:02:42 I deleted the cache here anyhow, but I think rotat
154 return cache.front().path;
155 }
156 }
157
222 const float right = size.width() * scale; 158 const float right = size.width() * scale;
223 // The bottom of the tab needs to be pixel-aligned or else when we call 159 // The bottom of the tab needs to be pixel-aligned or else when we call
224 // ClipPath with anti-aliasing enabled it can cause artifacts. 160 // ClipPath with anti-aliasing enabled it can cause artifacts.
225 const float bottom = std::ceil(size.height() * scale); 161 const float bottom = std::ceil(size.height() * scale);
226 const float unscaled_endcap_width = GetUnscaledEndcapWidth(); 162 const float unscaled_endcap_width = GetUnscaledEndcapWidth();
227 163
228 gfx::Path fill; 164 gfx::Path fill;
229 fill.moveTo(right - 1, bottom); 165 fill.moveTo(right - 1, bottom);
230 fill.rCubicTo(-0.75 * scale, 0, -1.625 * scale, -0.5 * scale, -2 * scale, 166 fill.rCubicTo(-0.75 * scale, 0, -1.625 * scale, -0.5 * scale, -2 * scale,
231 -1.5 * scale); 167 -1.5 * scale);
232 fill.lineTo(right - 1 - (unscaled_endcap_width - 2) * scale, 2.5 * scale); 168 fill.lineTo(right - 1 - (unscaled_endcap_width - 2) * scale, 2.5 * scale);
233 // Prevent overdraw in the center near minimum width (only happens if 169 // Prevent overdraw in the center near minimum width (only happens if
234 // scale < 2). We could instead avoid this by increasing the tab inset 170 // scale < 2). We could instead avoid this by increasing the tab inset
235 // values, but that would shift all the content inward as well, unless we 171 // values, but that would shift all the content inward as well, unless we
236 // then overlapped the content on the endcaps, by which point we'd have a 172 // then overlapped the content on the endcaps, by which point we'd have a
237 // huge mess. 173 // huge mess.
238 const float scaled_endcap_width = 1 + unscaled_endcap_width * scale; 174 const float scaled_endcap_width = 1 + unscaled_endcap_width * scale;
239 const float overlap = scaled_endcap_width * 2 - right; 175 const float overlap = scaled_endcap_width * 2 - right;
240 const float offset = (overlap > 0) ? (overlap / 2) : 0; 176 const float offset = (overlap > 0) ? (overlap / 2) : 0;
241 fill.rCubicTo(-0.375 * scale, -1 * scale, -1.25 * scale + offset, 177 fill.rCubicTo(-0.375 * scale, -1 * scale, -1.25 * scale + offset,
242 -1.5 * scale, -2 * scale + offset, -1.5 * scale); 178 -1.5 * scale, -2 * scale + offset, -1.5 * scale);
243 if (overlap < 0) 179 if (overlap < 0)
244 fill.lineTo(scaled_endcap_width, scale); 180 fill.lineTo(scaled_endcap_width, scale);
245 fill.rCubicTo(-0.75 * scale, 0, -1.625 * scale - offset, 0.5 * scale, 181 fill.rCubicTo(-0.75 * scale, 0, -1.625 * scale - offset, 0.5 * scale,
246 -2 * scale - offset, 1.5 * scale); 182 -2 * scale - offset, 1.5 * scale);
247 fill.lineTo(1 + 2 * scale, bottom - 1.5 * scale); 183 fill.lineTo(1 + 2 * scale, bottom - 1.5 * scale);
248 fill.rCubicTo(-0.375 * scale, scale, -1.25 * scale, 1.5 * scale, -2 * scale, 184 fill.rCubicTo(-0.375 * scale, scale, -1.25 * scale, 1.5 * scale, -2 * scale,
249 1.5 * scale); 185 1.5 * scale);
250 fill.close(); 186 fill.close();
187
188 // If the cache is max size we need to drop the least recently used from the
189 // cache. Then add the new path to the front of the cache.
190 if (cache.size() >= kCacheSize)
191 cache.pop_back();
192 cache.emplace_front();
193 cache.front().scale = scale;
Peter Kasting 2017/04/06 18:49:45 Nit: I'd rather define a constructor so we can jus
danakj 2017/04/07 19:10:49 Done. Made a constructor and a HasMatchingParamete
194 cache.front().size = size;
195 cache.front().path = fill;
196
251 return fill; 197 return fill;
252 } 198 }
253 199
254 // Returns a path corresponding to the tab's outer border for a given tab |size| 200 // Returns a path corresponding to the tab's outer border for a given tab |size|
255 // and |scale|. If |unscale_at_end| is true, this path will be normalized to a 201 // and |scale|. If |unscale_at_end| is true, this path will be normalized to a
256 // 1x scale by scaling by 1/scale before returning. If |extend_to_top| is true, 202 // 1x scale by scaling by 1/scale before returning. If |extend_to_top| is true,
257 // the path is extended vertically to the top of the tab bounds. The caller 203 // the path is extended vertically to the top of the tab bounds. The caller
258 // uses this for Fitts' Law purposes in maximized/fullscreen mode. 204 // uses this for Fitts' Law purposes in maximized/fullscreen mode.
259 gfx::Path GetBorderPath(float scale, 205 gfx::Path GetBorderPath(float scale,
260 bool unscale_at_end, 206 bool unscale_at_end,
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 alert_indicator_button_(nullptr), 473 alert_indicator_button_(nullptr),
528 close_button_(nullptr), 474 close_button_(nullptr),
529 title_(new views::Label()), 475 title_(new views::Label()),
530 tab_activated_with_last_tap_down_(false), 476 tab_activated_with_last_tap_down_(false),
531 hover_controller_(this), 477 hover_controller_(this),
532 showing_icon_(false), 478 showing_icon_(false),
533 showing_alert_indicator_(false), 479 showing_alert_indicator_(false),
534 showing_close_button_(false), 480 showing_close_button_(false),
535 button_color_(SK_ColorTRANSPARENT) { 481 button_color_(SK_ColorTRANSPARENT) {
536 DCHECK(controller); 482 DCHECK(controller);
537 InitTabResources();
538 483
539 // So we get don't get enter/exit on children and don't prematurely stop the 484 // So we get don't get enter/exit on children and don't prematurely stop the
540 // hover. 485 // hover.
541 set_notify_enter_exit_on_child(true); 486 set_notify_enter_exit_on_child(true);
542 487
543 set_id(VIEW_ID_TAB); 488 set_id(VIEW_ID_TAB);
544 489
545 SetBorder(views::CreateEmptyBorder(GetLayoutInsets(TAB))); 490 SetBorder(views::CreateEmptyBorder(GetLayoutInsets(TAB)));
546 491
547 title_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); 492 title_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 else 1061 else
1117 StopPulse(); 1062 StopPulse();
1118 } 1063 }
1119 1064
1120 void Tab::PaintTab(gfx::Canvas* canvas, const gfx::Path& clip) { 1065 void Tab::PaintTab(gfx::Canvas* canvas, const gfx::Path& clip) {
1121 const int kActiveTabFillId = 1066 const int kActiveTabFillId =
1122 GetThemeProvider()->HasCustomImage(IDR_THEME_TOOLBAR) ? IDR_THEME_TOOLBAR 1067 GetThemeProvider()->HasCustomImage(IDR_THEME_TOOLBAR) ? IDR_THEME_TOOLBAR
1123 : 0; 1068 : 0;
1124 const int y_offset = -GetLayoutInsets(TAB).top(); 1069 const int y_offset = -GetLayoutInsets(TAB).top();
1125 if (IsActive()) { 1070 if (IsActive()) {
1126 PaintTabBackgroundUsingFillId(canvas, canvas, true, kActiveTabFillId, 1071 PaintTabBackground(canvas, true /* active */, kActiveTabFillId, y_offset,
1127 y_offset); 1072 nullptr /* clip */);
1128 } else { 1073 } else {
1129 PaintInactiveTabBackground(canvas, clip); 1074 PaintInactiveTabBackground(canvas, clip);
1130 1075
1131 const double throb_value = GetThrobValue(); 1076 const double throb_value = GetThrobValue();
1132 if (throb_value > 0) { 1077 if (throb_value > 0) {
1133 canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff), 1078 canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff),
1134 GetLocalBounds()); 1079 GetLocalBounds());
1135 PaintTabBackgroundUsingFillId(canvas, canvas, true, kActiveTabFillId, 1080 PaintTabBackground(canvas, true /* active */, kActiveTabFillId, y_offset,
1136 y_offset); 1081 nullptr /* clip */);
1137 canvas->Restore(); 1082 canvas->Restore();
1138 } 1083 }
1139 } 1084 }
1140 1085
1141 if (showing_icon_) 1086 if (showing_icon_)
1142 PaintIcon(canvas); 1087 PaintIcon(canvas);
1143 } 1088 }
1144 1089
1145 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas, 1090 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas,
1146 const gfx::Path& clip) { 1091 const gfx::Path& clip) {
1147 bool has_custom_image; 1092 bool has_custom_image;
1148 int fill_id = controller_->GetBackgroundResourceId(&has_custom_image); 1093 int fill_id = controller_->GetBackgroundResourceId(&has_custom_image);
1149 const ui::ThemeProvider* tp = GetThemeProvider();
1150 1094
1151 // We only cache the image when it's the default image and we're not hovered,
1152 // to avoid caching a background image that isn't the same for all tabs.
1153 if (has_custom_image) { 1095 if (has_custom_image) {
1096 const ui::ThemeProvider* tp = GetThemeProvider();
1097
1154 // If the theme is providing a custom background image, then its top edge 1098 // 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 1099 // 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 1100 // 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, 1101 // is only providing a custom frame image, |has_custom_image| will be true,
1158 // but we should use the |background_offset_| here. 1102 // but we should use the |background_offset_| here.
1159 const int y_offset = 1103 int y_offset = tp->HasCustomImage(fill_id) ? 0 : background_offset_.y();
1160 tp->HasCustomImage(fill_id) ? 0 : background_offset_.y(); 1104 PaintTabBackground(canvas, false /* active */, fill_id, y_offset,
1161 PaintTabBackgroundUsingFillId(canvas, canvas, false, fill_id, y_offset); 1105 nullptr /* clip */);
1162 return; 1106 } else {
1163 } 1107 PaintTabBackground(canvas, false /* active */, 0 /* fill_id */,
1164 if (hover_controller_.ShouldDraw()) { 1108 0 /* y_offset */,
1165 PaintTabBackgroundUsingFillId(canvas, canvas, false, 0, 0); 1109 controller_->MaySetClip() ? &clip : nullptr);
1166 return;
1167 }
1168
1169 // For efficiency, we don't use separate fill and stroke images unless we
1170 // really need to clip the stroke and not the fill (for stacked tabs). This
1171 // saves memory and avoids an extra image draw at the cost of recalculating
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 }
1209
1210 void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* fill_canvas,
1211 gfx::Canvas* stroke_canvas,
1212 bool is_active,
1213 int fill_id,
1214 int y_offset) {
1215 gfx::Path fill;
1216 cc::PaintFlags flags;
1217 flags.setAntiAlias(true);
1218
1219 // Draw the fill.
1220 {
1221 gfx::ScopedCanvas scoped_canvas(fill_canvas);
1222 const float scale = fill_canvas->UndoDeviceScaleFactor();
1223 const ui::ThemeProvider* tp = GetThemeProvider();
1224 const SkColor toolbar_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR);
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 }
1255 }
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 } 1110 }
1273 } 1111 }
1274 1112
1113 void Tab::PaintTabBackground(gfx::Canvas* canvas,
1114 bool active,
1115 int fill_id,
1116 int y_offset,
1117 const gfx::Path* clip) {
1118 gfx::Path fill_path = GetFillPath(canvas->image_scale(), size());
1119
1120 PaintTabBackgroundFill(canvas, fill_path, active, fill_id, y_offset);
1121 {
Peter Kasting 2017/04/06 18:49:45 Nit: You could save a line or two and reduce the i
danakj 2017/04/07 19:10:49 Done.
1122 gfx::ScopedCanvas scoped_canvas(clip ? canvas : nullptr);
1123 if (clip)
1124 canvas->sk_canvas()->clipPath(*clip, SkClipOp::kDifference, true);
1125 PaintTabBackgroundStroke(canvas, fill_path, active);
1126 }
1127 }
1128
1129 void Tab::PaintTabBackgroundFill(gfx::Canvas* canvas,
1130 const gfx::Path& fill_path,
1131 bool active,
1132 int fill_id,
1133 int y_offset) {
1134 const ui::ThemeProvider* tp = GetThemeProvider();
1135 SkColor active_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR);
1136 SkColor inactive_color = tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB);
1137
1138 gfx::ScopedCanvas scoped_canvas(canvas);
1139 const float scale = canvas->UndoDeviceScaleFactor();
1140
1141 canvas->ClipPath(fill_path, true);
1142 if (fill_id) {
1143 gfx::ScopedCanvas scale_scoper(canvas);
1144 canvas->sk_canvas()->scale(scale, scale);
1145 canvas->TileImageInt(*tp->GetImageSkiaNamed(fill_id),
1146 GetMirroredX() + background_offset_.x(), y_offset, 0,
1147 0, width(), height());
1148 } else {
1149 cc::PaintFlags flags;
1150 flags.setAntiAlias(true);
1151 flags.setColor(active ? active_color : inactive_color);
1152 canvas->DrawRect(gfx::ScaleToEnclosingRect(GetLocalBounds(), scale), flags);
1153 }
1154
1155 if (!active && hover_controller_.ShouldDraw()) {
1156 SkPoint hover_location(gfx::PointToSkPoint(hover_controller_.location()));
1157 hover_location.scale(SkFloatToScalar(scale));
1158 const SkScalar kMinHoverRadius = 16;
1159 const SkScalar radius =
1160 std::max(SkFloatToScalar(width() / 4.f), kMinHoverRadius);
1161 DrawHighlight(canvas, hover_location, radius * scale,
1162 SkColorSetA(active_color, hover_controller_.GetAlpha()));
1163 }
1164 }
1165
1166 void Tab::PaintTabBackgroundStroke(gfx::Canvas* canvas,
1167 const gfx::Path& fill_path,
1168 bool active) {
1169 SkColor color = controller_->GetToolbarTopSeparatorColor();
1170
1171 gfx::ScopedCanvas scoped_canvas(canvas);
1172 const float scale = canvas->UndoDeviceScaleFactor();
1173
1174 gfx::Path stroke = GetBorderPath(scale, false, false, size());
1175 Op(stroke, fill_path, kDifference_SkPathOp, &stroke);
1176 if (!active) {
1177 // Clip out the bottom line; this will be drawn for us by
1178 // TabStrip::PaintChildren().
1179 canvas->ClipRect(gfx::RectF(width() * scale, height() * scale - 1));
1180 }
1181 cc::PaintFlags flags;
1182 flags.setAntiAlias(true);
1183 flags.setColor(color);
1184 canvas->DrawPath(stroke, flags);
1185 }
1186
1275 void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( 1187 void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon(
1276 gfx::Canvas* canvas, 1188 gfx::Canvas* canvas,
1277 const gfx::Rect& favicon_draw_bounds) { 1189 const gfx::Rect& favicon_draw_bounds) {
1278 // The pinned tab title changed indicator consists of two parts: 1190 // The pinned tab title changed indicator consists of two parts:
1279 // . a clear (totally transparent) part over the bottom right (or left in rtl) 1191 // . 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 1192 // of the favicon. This is done by drawing the favicon to a canvas, then
1281 // drawing the clear part on top of the favicon. 1193 // drawing the clear part on top of the favicon.
1282 // . a circle in the bottom right (or left in rtl) of the favicon. 1194 // . a circle in the bottom right (or left in rtl) of the favicon.
1283 if (!favicon_.isNull()) { 1195 if (!favicon_.isNull()) {
1284 const float kIndicatorCropRadius = 4.5; 1196 const float kIndicatorCropRadius = 4.5;
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1486 gfx::Rect bounds = favicon_bounds_; 1398 gfx::Rect bounds = favicon_bounds_;
1487 if (bounds.IsEmpty()) 1399 if (bounds.IsEmpty())
1488 return; 1400 return;
1489 1401
1490 // Extends the area to the bottom when the crash animation is in progress. 1402 // Extends the area to the bottom when the crash animation is in progress.
1491 if (crash_icon_animation_->is_animating()) 1403 if (crash_icon_animation_->is_animating())
1492 bounds.set_height(height() - bounds.y()); 1404 bounds.set_height(height() - bounds.y());
1493 bounds.set_x(GetMirroredXForRect(bounds)); 1405 bounds.set_x(GetMirroredXForRect(bounds));
1494 SchedulePaintInRect(bounds); 1406 SchedulePaintInRect(bounds);
1495 } 1407 }
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