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 <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/debug/alias.h" | 10 #include "base/debug/alias.h" |
(...skipping 1111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1122 // The second part parts the remaining |eye_width| on the left. | 1122 // The second part parts the remaining |eye_width| on the left. |
1123 int left_eye_width = eye_offset + eye_width - bar_rect.width(); | 1123 int left_eye_width = eye_offset + eye_width - bar_rect.width(); |
1124 gfx::Rect left_eye_rect( | 1124 gfx::Rect left_eye_rect( |
1125 bar_rect.x(), 0, left_eye_width, kImmersiveBarHeight); | 1125 bar_rect.x(), 0, left_eye_width, kImmersiveBarHeight); |
1126 canvas->FillRect(left_eye_rect, kEyeColor); | 1126 canvas->FillRect(left_eye_rect, kEyeColor); |
1127 } | 1127 } |
1128 } | 1128 } |
1129 } | 1129 } |
1130 | 1130 |
1131 void Tab::PaintTabBackground(gfx::Canvas* canvas) { | 1131 void Tab::PaintTabBackground(gfx::Canvas* canvas) { |
| 1132 const int kActiveTabFillId = IDR_THEME_TOOLBAR; |
| 1133 const bool has_custom_image = |
| 1134 GetThemeProvider()->HasCustomImage(kActiveTabFillId); |
1132 if (IsActive()) { | 1135 if (IsActive()) { |
1133 PaintActiveTabBackground(canvas); | 1136 PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId, |
| 1137 has_custom_image, 0); |
1134 } else { | 1138 } else { |
1135 if (pinned_title_change_animation_ && | 1139 if (pinned_title_change_animation_ && |
1136 pinned_title_change_animation_->is_animating()) | 1140 pinned_title_change_animation_->is_animating()) |
1137 PaintInactiveTabBackgroundWithTitleChange(canvas); | 1141 PaintInactiveTabBackgroundWithTitleChange(canvas); |
1138 else | 1142 else |
1139 PaintInactiveTabBackground(canvas); | 1143 PaintInactiveTabBackground(canvas); |
1140 | 1144 |
1141 const double throb_value = GetThrobValue(); | 1145 const double throb_value = GetThrobValue(); |
1142 if (throb_value > 0) { | 1146 if (throb_value > 0) { |
1143 canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff), | 1147 canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff), |
1144 GetLocalBounds()); | 1148 GetLocalBounds()); |
1145 PaintActiveTabBackground(canvas); | 1149 PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId, |
| 1150 has_custom_image, 0); |
1146 canvas->Restore(); | 1151 canvas->Restore(); |
1147 } | 1152 } |
1148 } | 1153 } |
1149 } | 1154 } |
1150 | 1155 |
1151 void Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) { | 1156 void Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) { |
1152 const int kPinnedTitleChangeGradientRadius = 20; | 1157 const int kPinnedTitleChangeGradientRadius = 20; |
1153 const float radius = kPinnedTitleChangeGradientRadius; | 1158 const float radius = kPinnedTitleChangeGradientRadius; |
1154 double x = radius; | 1159 double x = radius; |
1155 int alpha = 255; | 1160 int alpha = 255; |
(...skipping 11 matching lines...) Expand all Loading... |
1167 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); | 1172 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); |
1168 canvas->DrawImageInt(background_image, 0, 0); | 1173 canvas->DrawImageInt(background_image, 0, 0); |
1169 gfx::Canvas hover_canvas(size(), canvas->image_scale(), false); | 1174 gfx::Canvas hover_canvas(size(), canvas->image_scale(), false); |
1170 DrawHighlight(&hover_canvas, p, SkFloatToScalar(radius), alpha); | 1175 DrawHighlight(&hover_canvas, p, SkFloatToScalar(radius), alpha); |
1171 gfx::ImageSkia hover_image = gfx::ImageSkiaOperations::CreateMaskedImage( | 1176 gfx::ImageSkia hover_image = gfx::ImageSkiaOperations::CreateMaskedImage( |
1172 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); | 1177 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); |
1173 canvas->DrawImageInt(hover_image, 0, 0); | 1178 canvas->DrawImageInt(hover_image, 0, 0); |
1174 } | 1179 } |
1175 | 1180 |
1176 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { | 1181 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { |
1177 int tab_id, frame_id; | 1182 int fill_id, frame_id; |
1178 GetTabIdAndFrameId(GetWidget(), &tab_id, &frame_id); | 1183 GetTabIdAndFrameId(GetWidget(), &fill_id, &frame_id); |
1179 // HasCustomImage() is only true if the theme provides the image. However, | 1184 // HasCustomImage() is only true if the theme provides the image. However, |
1180 // even if the theme does not provide a tab background, the theme machinery | 1185 // even if the theme does not provide a tab background, the theme machinery |
1181 // will make one if given a frame image. | 1186 // will make one if given a frame image. |
1182 ui::ThemeProvider* theme_provider = GetThemeProvider(); | 1187 ui::ThemeProvider* theme_provider = GetThemeProvider(); |
1183 const bool has_custom_image = theme_provider->HasCustomImage(tab_id) || | 1188 const bool has_custom_image = theme_provider->HasCustomImage(fill_id) || |
1184 (frame_id != 0 && theme_provider->HasCustomImage(frame_id)); | 1189 (frame_id != 0 && theme_provider->HasCustomImage(frame_id)); |
1185 | 1190 |
1186 // Explicitly map the id so we cache correctly. | 1191 // Explicitly map the id so we cache correctly. |
1187 const chrome::HostDesktopType host_desktop_type = GetHostDesktopType(this); | 1192 const chrome::HostDesktopType host_desktop_type = GetHostDesktopType(this); |
1188 tab_id = chrome::MapThemeImage(host_desktop_type, tab_id); | 1193 fill_id = chrome::MapThemeImage(host_desktop_type, fill_id); |
| 1194 |
| 1195 // If the theme is providing a custom background image, then its top edge |
| 1196 // should be at the top of the tab. Otherwise, we assume that the background |
| 1197 // image is a composited foreground + frame image. |
| 1198 const int y_offset = GetThemeProvider()->HasCustomImage(fill_id) ? |
| 1199 0 : background_offset_.y(); |
1189 | 1200 |
1190 // We only cache the image when it's the default image and we're not hovered, | 1201 // We only cache the image when it's the default image and we're not hovered, |
1191 // to avoid caching a background image that isn't the same for all tabs. | 1202 // to avoid caching a background image that isn't the same for all tabs. |
1192 if (!has_custom_image && !hover_controller_.ShouldDraw()) { | 1203 if (!has_custom_image && !hover_controller_.ShouldDraw()) { |
1193 ui::ScaleFactor scale_factor = | 1204 ui::ScaleFactor scale_factor = |
1194 ui::GetSupportedScaleFactor(canvas->image_scale()); | 1205 ui::GetSupportedScaleFactor(canvas->image_scale()); |
1195 gfx::ImageSkia cached_image(GetCachedImage(tab_id, size(), scale_factor)); | 1206 gfx::ImageSkia cached_image(GetCachedImage(fill_id, size(), scale_factor)); |
1196 if (cached_image.width() == 0) { | 1207 if (cached_image.width() == 0) { |
1197 gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false); | 1208 gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false); |
1198 PaintInactiveTabBackgroundUsingResourceId(&tmp_canvas, tab_id); | 1209 PaintTabBackgroundUsingFillId(&tmp_canvas, false, fill_id, false, |
| 1210 y_offset); |
1199 cached_image = gfx::ImageSkia(tmp_canvas.ExtractImageRep()); | 1211 cached_image = gfx::ImageSkia(tmp_canvas.ExtractImageRep()); |
1200 SetCachedImage(tab_id, scale_factor, cached_image); | 1212 SetCachedImage(fill_id, scale_factor, cached_image); |
1201 } | 1213 } |
1202 canvas->DrawImageInt(cached_image, 0, 0); | 1214 canvas->DrawImageInt(cached_image, 0, 0); |
1203 } else { | 1215 } else { |
1204 PaintInactiveTabBackgroundUsingResourceId(canvas, tab_id); | 1216 PaintTabBackgroundUsingFillId(canvas, false, fill_id, has_custom_image, |
| 1217 y_offset); |
1205 } | 1218 } |
1206 } | 1219 } |
1207 | 1220 |
1208 void Tab::PaintInactiveTabBackgroundUsingResourceId(gfx::Canvas* canvas, | 1221 void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* canvas, |
1209 int tab_id) { | 1222 bool is_active, |
1210 gfx::ImageSkia* tab_background = | 1223 int fill_id, |
1211 GetThemeProvider()->GetImageSkiaNamed(tab_id); | 1224 bool has_custom_image, |
| 1225 int y_offset) { |
| 1226 gfx::ImageSkia* fill_image = GetThemeProvider()->GetImageSkiaNamed(fill_id); |
1212 // The tab image needs to be lined up with the background image | 1227 // The tab image needs to be lined up with the background image |
1213 // so that it feels partially transparent. These offsets represent the tab | 1228 // so that it feels partially transparent. These offsets represent the tab |
1214 // position within the frame background image. | 1229 // position within the frame background image. |
1215 const int x_offset = GetMirroredX() + background_offset_.x(); | 1230 const int x_offset = GetMirroredX() + background_offset_.x(); |
1216 | 1231 |
1217 // If the theme is providing a custom background image, then its top edge | |
1218 // should be at the top of the tab. Otherwise, we assume that the background | |
1219 // image is a composited foreground + frame image. | |
1220 const int y_offset = GetThemeProvider()->HasCustomImage(tab_id) ? | |
1221 0 : background_offset_.y(); | |
1222 | |
1223 const gfx::Insets tab_insets(GetLayoutInsets(TAB)); | |
1224 // Don't draw over the toolbar, but do include the 1 px divider stroke at the | |
1225 // bottom. | |
1226 const int toolbar_overlap = tab_insets.bottom() - 1; | |
1227 | |
1228 const SkScalar radius = SkFloatToScalar(width() / 3.f); | 1232 const SkScalar radius = SkFloatToScalar(width() / 3.f); |
1229 const bool draw_hover = hover_controller_.ShouldDraw() && radius > 0; | 1233 const bool draw_hover = |
| 1234 !is_active && hover_controller_.ShouldDraw() && radius > 0; |
1230 SkPoint hover_location(PointToSkPoint(hover_controller_.location())); | 1235 SkPoint hover_location(PointToSkPoint(hover_controller_.location())); |
1231 const SkAlpha hover_alpha = hover_controller_.GetAlpha(); | 1236 const SkAlpha hover_alpha = hover_controller_.GetAlpha(); |
1232 | 1237 |
1233 // Draw everything to a temporary canvas so we can extract an image for use in | 1238 if (draw_hover) { |
1234 // masking the hover glow. | 1239 // Draw everything to a temporary canvas so we can extract an image for use |
1235 gfx::Canvas background_canvas(size(), canvas->image_scale(), false); | 1240 // in masking the hover glow. |
| 1241 gfx::Canvas background_canvas(size(), canvas->image_scale(), false); |
| 1242 PaintTabFill(&background_canvas, fill_image, x_offset, y_offset, is_active); |
| 1243 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); |
| 1244 canvas->DrawImageInt(background_image, 0, 0); |
1236 | 1245 |
1237 // Draw left edge. | |
1238 gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( | |
1239 *tab_background, x_offset, y_offset, mask_images_.l_width, height()); | |
1240 gfx::ImageSkia theme_l = | |
1241 gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *mask_images_.image_l); | |
1242 background_canvas.DrawImageInt( | |
1243 theme_l, 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, 0, 0, | |
1244 theme_l.width(), theme_l.height() - toolbar_overlap, false); | |
1245 | |
1246 // Draw right edge. | |
1247 gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( | |
1248 *tab_background, x_offset + width() - mask_images_.r_width, y_offset, | |
1249 mask_images_.r_width, height()); | |
1250 gfx::ImageSkia theme_r = | |
1251 gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *mask_images_.image_r); | |
1252 background_canvas.DrawImageInt(theme_r, 0, 0, theme_r.width(), | |
1253 theme_r.height() - toolbar_overlap, | |
1254 width() - theme_r.width(), 0, theme_r.width(), | |
1255 theme_r.height() - toolbar_overlap, false); | |
1256 | |
1257 // Draw center. Instead of masking out the top portion we simply skip over | |
1258 // it by incrementing by the top padding, since it's a simple rectangle. | |
1259 background_canvas.TileImageInt( | |
1260 *tab_background, x_offset + mask_images_.l_width, | |
1261 y_offset + tab_insets.top(), mask_images_.l_width, tab_insets.top(), | |
1262 width() - mask_images_.l_width - mask_images_.r_width, | |
1263 height() - tab_insets.top() - toolbar_overlap); | |
1264 | |
1265 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); | |
1266 canvas->DrawImageInt(background_image, 0, 0); | |
1267 | |
1268 if (draw_hover) { | |
1269 gfx::Canvas hover_canvas(size(), canvas->image_scale(), false); | 1246 gfx::Canvas hover_canvas(size(), canvas->image_scale(), false); |
1270 DrawHighlight(&hover_canvas, hover_location, radius, hover_alpha); | 1247 DrawHighlight(&hover_canvas, hover_location, radius, hover_alpha); |
1271 gfx::ImageSkia result = gfx::ImageSkiaOperations::CreateMaskedImage( | 1248 gfx::ImageSkia result = gfx::ImageSkiaOperations::CreateMaskedImage( |
1272 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); | 1249 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); |
1273 canvas->DrawImageInt(result, 0, 0); | 1250 canvas->DrawImageInt(result, 0, 0); |
| 1251 } else { |
| 1252 PaintTabFill(canvas, fill_image, x_offset, y_offset, is_active); |
1274 } | 1253 } |
1275 | 1254 |
1276 // Now draw the stroke, highlights, and shadows around the tab edge. | 1255 // Now draw the stroke, highlights, and shadows around the tab edge. |
1277 TabImages* stroke_images = &inactive_images_; | 1256 TabImages* stroke_images = is_active ? &active_images_ : &inactive_images_; |
1278 canvas->DrawImageInt(*stroke_images->image_l, 0, 0); | 1257 canvas->DrawImageInt(*stroke_images->image_l, 0, 0); |
1279 canvas->TileImageInt( | 1258 canvas->TileImageInt( |
1280 *stroke_images->image_c, stroke_images->l_width, 0, | 1259 *stroke_images->image_c, stroke_images->l_width, 0, |
1281 width() - stroke_images->l_width - stroke_images->r_width, height()); | 1260 width() - stroke_images->l_width - stroke_images->r_width, height()); |
1282 canvas->DrawImageInt(*stroke_images->image_r, | 1261 canvas->DrawImageInt(*stroke_images->image_r, |
1283 width() - stroke_images->r_width, 0); | 1262 width() - stroke_images->r_width, 0); |
1284 } | 1263 } |
1285 | 1264 |
1286 void Tab::PaintActiveTabBackground(gfx::Canvas* canvas) { | 1265 void Tab::PaintTabFill(gfx::Canvas* canvas, |
1287 gfx::ImageSkia* tab_background = | 1266 gfx::ImageSkia* fill_image, |
1288 GetThemeProvider()->GetImageSkiaNamed(IDR_THEME_TOOLBAR); | 1267 int x_offset, |
1289 int x_offset = GetMirroredX() + background_offset_.x(); | 1268 int y_offset, |
1290 | 1269 bool is_active) { |
1291 const gfx::Insets tab_insets(GetLayoutInsets(TAB)); | 1270 const gfx::Insets tab_insets(GetLayoutInsets(TAB)); |
| 1271 // If this isn't the foreground tab, don't draw over the toolbar, but do |
| 1272 // include the 1 px divider stroke at the bottom. |
| 1273 const int toolbar_overlap = is_active ? 0 : (tab_insets.bottom() - 1); |
1292 | 1274 |
1293 // Draw left edge. | 1275 // Draw left edge. |
1294 gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( | 1276 gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( |
1295 *tab_background, x_offset, 0, mask_images_.l_width, height()); | 1277 *fill_image, x_offset, y_offset, mask_images_.l_width, height()); |
1296 gfx::ImageSkia theme_l = | 1278 gfx::ImageSkia theme_l = |
1297 gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *mask_images_.image_l); | 1279 gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *mask_images_.image_l); |
1298 canvas->DrawImageInt( | 1280 canvas->DrawImageInt( |
1299 theme_l, 0, 0, theme_l.width(), theme_l.height(), 0, 0, theme_l.width(), | 1281 theme_l, 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, 0, 0, |
1300 theme_l.height(), false); | 1282 theme_l.width(), theme_l.height() - toolbar_overlap, false); |
1301 | 1283 |
1302 // Draw right edge. | 1284 // Draw right edge. |
1303 gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( | 1285 gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( |
1304 *tab_background, x_offset + width() - mask_images_.r_width, 0, | 1286 *fill_image, x_offset + width() - mask_images_.r_width, y_offset, |
1305 mask_images_.r_width, height()); | 1287 mask_images_.r_width, height()); |
1306 gfx::ImageSkia theme_r = | 1288 gfx::ImageSkia theme_r = |
1307 gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *mask_images_.image_r); | 1289 gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *mask_images_.image_r); |
1308 canvas->DrawImageInt(theme_r, 0, 0, theme_r.width(), theme_r.height(), | 1290 canvas->DrawImageInt(theme_r, 0, 0, theme_r.width(), |
| 1291 theme_r.height() - toolbar_overlap, |
1309 width() - theme_r.width(), 0, theme_r.width(), | 1292 width() - theme_r.width(), 0, theme_r.width(), |
1310 theme_r.height(), false); | 1293 theme_r.height() - toolbar_overlap, false); |
1311 | 1294 |
1312 // Draw center. Instead of masking out the top portion we simply skip over it | 1295 // Draw center. Instead of masking out the top portion we simply skip over it |
1313 // by incrementing by the top padding, since it's a simple rectangle. | 1296 // by incrementing by the top padding, since it's a simple rectangle. |
1314 canvas->TileImageInt(*tab_background, x_offset + mask_images_.l_width, | 1297 canvas->TileImageInt(*fill_image, x_offset + mask_images_.l_width, |
1315 tab_insets.top(), mask_images_.l_width, tab_insets.top(), | 1298 y_offset + tab_insets.top(), mask_images_.l_width, |
| 1299 tab_insets.top(), |
1316 width() - mask_images_.l_width - mask_images_.r_width, | 1300 width() - mask_images_.l_width - mask_images_.r_width, |
1317 height() - tab_insets.top()); | 1301 height() - tab_insets.top() - toolbar_overlap); |
1318 | |
1319 // Now draw the stroke, highlights, and shadows around the tab edge. | |
1320 TabImages* stroke_images = &active_images_; | |
1321 canvas->DrawImageInt(*stroke_images->image_l, 0, 0); | |
1322 canvas->TileImageInt( | |
1323 *stroke_images->image_c, stroke_images->l_width, 0, | |
1324 width() - stroke_images->l_width - stroke_images->r_width, height()); | |
1325 canvas->DrawImageInt(*stroke_images->image_r, | |
1326 width() - stroke_images->r_width, 0); | |
1327 } | 1302 } |
1328 | 1303 |
1329 void Tab::PaintIcon(gfx::Canvas* canvas) { | 1304 void Tab::PaintIcon(gfx::Canvas* canvas) { |
1330 gfx::Rect bounds = favicon_bounds_; | 1305 gfx::Rect bounds = favicon_bounds_; |
1331 bounds.set_x(GetMirroredXForRect(bounds)); | 1306 bounds.set_x(GetMirroredXForRect(bounds)); |
1332 bounds.Offset(0, favicon_hiding_offset_); | 1307 bounds.Offset(0, favicon_hiding_offset_); |
1333 bounds.Intersect(GetContentsBounds()); | 1308 bounds.Intersect(GetContentsBounds()); |
1334 if (bounds.IsEmpty()) | 1309 if (bounds.IsEmpty()) |
1335 return; | 1310 return; |
1336 | 1311 |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1591 const gfx::ImageSkia& image) { | 1566 const gfx::ImageSkia& image) { |
1592 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); | 1567 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); |
1593 ImageCacheEntry entry; | 1568 ImageCacheEntry entry; |
1594 entry.resource_id = resource_id; | 1569 entry.resource_id = resource_id; |
1595 entry.scale_factor = scale_factor; | 1570 entry.scale_factor = scale_factor; |
1596 entry.image = image; | 1571 entry.image = image; |
1597 image_cache_->push_front(entry); | 1572 image_cache_->push_front(entry); |
1598 if (image_cache_->size() > kMaxImageCacheSize) | 1573 if (image_cache_->size() > kMaxImageCacheSize) |
1599 image_cache_->pop_back(); | 1574 image_cache_->pop_back(); |
1600 } | 1575 } |
OLD | NEW |