Index: chrome/browser/ui/views/tabs/tab.cc |
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc |
index c76f68ce3437911c58368c7bbb32e4e5370cfdb4..580ce9c781d2ff7ac118349cbc63b174ce01efb1 100644 |
--- a/chrome/browser/ui/views/tabs/tab.cc |
+++ b/chrome/browser/ui/views/tabs/tab.cc |
@@ -116,6 +116,135 @@ const int kImmersiveLoadingStepCount = 32; |
const char kTabCloseButtonName[] = "TabCloseButton"; |
+//////////////////////////////////////////////////////////////////////////////// |
+// ImageCacheEntryMetadata |
+// |
+// All metadata necessary to uniquely identify a cached image. |
+struct ImageCacheEntryMetadata { |
+ ImageCacheEntryMetadata(int resource_id, |
+ SkColor fill_color, |
+ SkColor stroke_color, |
+ ui::ScaleFactor scale_factor, |
+ const gfx::Size& size); |
+ |
+ ~ImageCacheEntryMetadata(); |
+ |
+ bool operator==(const ImageCacheEntryMetadata& rhs) const; |
+ |
+ int resource_id; // Only needed by pre-MD |
+ SkColor fill_color; // Both colors only needed by MD |
+ SkColor stroke_color; |
+ ui::ScaleFactor scale_factor; |
+ gfx::Size size; |
+}; |
+ |
+ImageCacheEntryMetadata::ImageCacheEntryMetadata(int resource_id, |
+ SkColor fill_color, |
+ SkColor stroke_color, |
+ ui::ScaleFactor scale_factor, |
+ const gfx::Size& size) |
+ : resource_id(resource_id), |
+ fill_color(fill_color), |
+ stroke_color(stroke_color), |
+ scale_factor(scale_factor), |
+ size(size) { |
+ DCHECK_NE(ui::SCALE_FACTOR_NONE, scale_factor); |
+ |
+ // Some fields are only relevant for pre-MD vs. MD. Erase the irrelevant ones |
+ // so they don't cause incorrect cache misses. |
+ // TODO(pkasting): Remove |resource_id| field when non-MD code is deleted. |
+ if (ui::MaterialDesignController::IsModeMaterial()) |
+ resource_id = 0; |
+ else |
+ fill_color = stroke_color = SK_ColorTRANSPARENT; |
+} |
+ |
+ImageCacheEntryMetadata::~ImageCacheEntryMetadata() {} |
+ |
+bool ImageCacheEntryMetadata::operator==( |
+ const ImageCacheEntryMetadata& rhs) const { |
+ return resource_id == rhs.resource_id && fill_color == rhs.fill_color && |
+ stroke_color == rhs.stroke_color && scale_factor == rhs.scale_factor && |
+ size == rhs.size; |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// ImageCacheEntry and cache management |
+// |
+// A cached image and the metadata used to generate it. |
+struct ImageCacheEntry { |
+ ImageCacheEntry(const ImageCacheEntryMetadata& metadata, |
+ const gfx::ImageSkia& image); |
+ ~ImageCacheEntry(); |
+ |
+ ImageCacheEntryMetadata metadata; |
+ gfx::ImageSkia image; |
+}; |
+ |
+ImageCacheEntry::ImageCacheEntry(const ImageCacheEntryMetadata& metadata, |
+ const gfx::ImageSkia& image) |
+ : metadata(metadata), image(image) {} |
+ |
+ImageCacheEntry::~ImageCacheEntry() {} |
+ |
+typedef std::list<ImageCacheEntry> ImageCache; |
+ |
+// As the majority of the tabs are inactive, and painting tabs is slowish, |
+// we cache a handful of the inactive tab backgrounds here. |
+static ImageCache* image_cache = NULL; |
Greg Levin
2016/07/14 18:26:45
Is there a preferred naming convention for static
msw
2016/07/14 20:14:49
I think 'g' is commonly used as a prefix for file-
|
+ |
+struct TabImages { |
+ gfx::ImageSkia* image_l; |
+ gfx::ImageSkia* image_c; |
+ gfx::ImageSkia* image_r; |
+ int l_width; |
+ int r_width; |
+}; |
+static TabImages active_images = {0}; |
+static TabImages inactive_images = {0}; |
+static TabImages mask_images = {0}; |
+ |
+// Loads the images to be used for the tab background. |
+void LoadTabImages() { |
+ image_cache->clear(); |
+ |
+ // We're not letting people override tab images just yet. |
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
+ |
+ active_images.image_l = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_LEFT); |
+ active_images.image_c = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_CENTER); |
+ active_images.image_r = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_RIGHT); |
+ active_images.l_width = active_images.image_l->width(); |
+ active_images.r_width = active_images.image_r->width(); |
+ |
+ inactive_images.image_l = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_LEFT); |
+ inactive_images.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); |
+ inactive_images.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); |
+ inactive_images.l_width = inactive_images.image_l->width(); |
+ inactive_images.r_width = inactive_images.image_r->width(); |
+ |
+ mask_images.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); |
+ mask_images.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); |
+ mask_images.l_width = mask_images.image_l->width(); |
+ mask_images.r_width = mask_images.image_r->width(); |
+} |
+ |
+// Performs a one-time initialization of static resources such as tab images. |
+void InitTabResources() { |
+ static bool initialized = false; |
+ if (initialized) |
+ return; |
+ |
+ initialized = true; |
+ image_cache = new ImageCache(); |
+ |
+ // Load the tab images once now, and maybe again later if the theme changes. |
+ LoadTabImages(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Drawing and utility functions |
+ |
// Returns the width of the tab endcap at scale 1. More precisely, this is the |
// width of the curve making up either the outer or inner edge of the stroke; |
// since these two curves are horizontally offset by 1 px (regardless of scale), |
@@ -147,6 +276,119 @@ bool ShouldThemifyFaviconForUrl(const GURL& url) { |
url.host() != chrome::kChromeUIUberHost; |
} |
+// Computes a path corresponding to the tab's content region inside the outer |
+// stroke. |
Greg Levin
2016/07/14 18:26:45
These three functions were *almost* static (just n
msw
2016/07/14 20:14:49
Acknowledged.
|
+void GetFillPath(float scale, const gfx::Size& size, SkPath* fill) { |
+ const float right = size.width() * scale; |
+ // The bottom of the tab needs to be pixel-aligned or else when we call |
+ // ClipPath with anti-aliasing enabled it can cause artifacts. |
+ const float bottom = std::ceil(size.height() * scale); |
+ const float unscaled_endcap_width = GetUnscaledEndcapWidth(); |
+ |
+ fill->moveTo(right - 1, bottom); |
+ fill->rCubicTo(-0.75 * scale, 0, -1.625 * scale, -0.5 * scale, -2 * scale, |
+ -1.5 * scale); |
+ fill->lineTo(right - 1 - (unscaled_endcap_width - 2) * scale, 2.5 * scale); |
+ // Prevent overdraw in the center near minimum width (only happens if |
+ // scale < 2). We could instead avoid this by increasing the tab inset |
+ // values, but that would shift all the content inward as well, unless we |
+ // then overlapped the content on the endcaps, by which point we'd have a |
+ // huge mess. |
+ const float scaled_endcap_width = 1 + unscaled_endcap_width * scale; |
+ const float overlap = scaled_endcap_width * 2 - right; |
+ const float offset = (overlap > 0) ? (overlap / 2) : 0; |
+ fill->rCubicTo(-0.375 * scale, -1 * scale, -1.25 * scale + offset, |
+ -1.5 * scale, -2 * scale + offset, -1.5 * scale); |
+ if (overlap < 0) |
+ fill->lineTo(scaled_endcap_width, scale); |
+ fill->rCubicTo(-0.75 * scale, 0, -1.625 * scale - offset, 0.5 * scale, |
+ -2 * scale - offset, 1.5 * scale); |
+ fill->lineTo(1 + 2 * scale, bottom - 1.5 * scale); |
+ fill->rCubicTo(-0.375 * scale, scale, -1.25 * scale, 1.5 * scale, -2 * scale, |
+ 1.5 * scale); |
+ fill->close(); |
+} |
+ |
+// Computes a path corresponding to the tab's outer border for a given |scale| |
+// and stores it in |path|. If |extend_to_top| is true, the path is extended |
+// vertically to the top of the tab bounds. The caller uses this for Fitts' |
+// Law purposes in maximized/fullscreen mode. |
+void GetBorderPath(float scale, |
+ const gfx::Size& size, |
+ bool extend_to_top, |
+ SkPath* path) { |
+ const float top = scale - 1; |
+ const float right = size.width() * scale; |
+ const float bottom = size.height() * scale; |
+ const float unscaled_endcap_width = GetUnscaledEndcapWidth(); |
+ |
+ path->moveTo(0, bottom); |
+ path->rLineTo(0, -1); |
+ path->rCubicTo(0.75 * scale, 0, 1.625 * scale, -0.5 * scale, 2 * scale, |
+ -1.5 * scale); |
+ path->lineTo((unscaled_endcap_width - 2) * scale, top + 1.5 * scale); |
+ if (extend_to_top) { |
+ // Create the vertical extension by extending the side diagonals until they |
+ // reach the top of the bounds. |
+ const float dy = 2.5 * scale - 1; |
+ const float dx = Tab::GetInverseDiagonalSlope() * dy; |
+ path->rLineTo(dx, -dy); |
+ path->lineTo(right - (unscaled_endcap_width - 2) * scale - dx, 0); |
+ path->rLineTo(dx, dy); |
+ } else { |
+ path->rCubicTo(0.375 * scale, -scale, 1.25 * scale, -1.5 * scale, 2 * scale, |
+ -1.5 * scale); |
+ path->lineTo(right - unscaled_endcap_width * scale, top); |
+ path->rCubicTo(0.75 * scale, 0, 1.625 * scale, 0.5 * scale, 2 * scale, |
+ 1.5 * scale); |
+ } |
+ path->lineTo(right - 2 * scale, bottom - 1 - 1.5 * scale); |
+ path->rCubicTo(0.375 * scale, scale, 1.25 * scale, 1.5 * scale, 2 * scale, |
+ 1.5 * scale); |
+ path->rLineTo(0, 1); |
+ path->close(); |
+} |
+ |
+void PaintTabFill(gfx::Canvas* canvas, |
+ gfx::ImageSkia* fill_image, |
+ int x_offset, |
+ int y_offset, |
+ const gfx::Size& size, |
+ bool is_active) { |
+ const gfx::Insets tab_insets(GetLayoutInsets(TAB)); |
+ // If this isn't the foreground tab, don't draw over the toolbar, but do |
+ // include the 1 px divider stroke at the bottom. |
+ const int toolbar_overlap = is_active ? 0 : (tab_insets.bottom() - 1); |
+ |
+ // Draw left edge. |
+ gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( |
+ *fill_image, x_offset, y_offset, mask_images.l_width, size.height()); |
+ gfx::ImageSkia theme_l = |
+ gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *mask_images.image_l); |
+ canvas->DrawImageInt( |
+ theme_l, 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, 0, 0, |
+ theme_l.width(), theme_l.height() - toolbar_overlap, false); |
+ |
+ // Draw right edge. |
+ gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( |
+ *fill_image, x_offset + size.width() - mask_images.r_width, y_offset, |
+ mask_images.r_width, size.height()); |
+ gfx::ImageSkia theme_r = |
+ gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *mask_images.image_r); |
+ canvas->DrawImageInt(theme_r, 0, 0, theme_r.width(), |
+ theme_r.height() - toolbar_overlap, |
+ size.width() - theme_r.width(), 0, theme_r.width(), |
+ theme_r.height() - toolbar_overlap, false); |
+ |
+ // Draw center. Instead of masking out the top portion we simply skip over it |
+ // by incrementing by the top padding, since it's a simple rectangle. |
+ canvas->TileImageInt(*fill_image, x_offset + mask_images.l_width, |
+ y_offset + tab_insets.top(), mask_images.l_width, |
+ tab_insets.top(), |
+ size.width() - mask_images.l_width - mask_images.r_width, |
+ size.height() - tab_insets.top() - toolbar_overlap); |
+} |
+ |
} // namespace |
//////////////////////////////////////////////////////////////////////////////// |
@@ -412,88 +654,10 @@ void Tab::ThrobberView::OnPaint(gfx::Canvas* canvas) { |
} |
//////////////////////////////////////////////////////////////////////////////// |
-// Tab::ImageCacheEntryMetadata |
- |
-struct Tab::ImageCacheEntryMetadata { |
- ImageCacheEntryMetadata(int resource_id, |
- SkColor fill_color, |
- SkColor stroke_color, |
- ui::ScaleFactor scale_factor, |
- const gfx::Size& size); |
- |
- ~ImageCacheEntryMetadata(); |
- |
- // Making this a non-member would require a friend declaration in Tab. Bleh. |
- bool operator==(const ImageCacheEntryMetadata& rhs) const; |
- |
- int resource_id; // Only needed by pre-MD |
- SkColor fill_color; // Both colors only needed by MD |
- SkColor stroke_color; |
- ui::ScaleFactor scale_factor; |
- gfx::Size size; |
-}; |
- |
-Tab::ImageCacheEntryMetadata::ImageCacheEntryMetadata( |
- int resource_id, |
- SkColor fill_color, |
- SkColor stroke_color, |
- ui::ScaleFactor scale_factor, |
- const gfx::Size& size) |
- : resource_id(resource_id), |
- fill_color(fill_color), |
- stroke_color(stroke_color), |
- scale_factor(scale_factor), |
- size(size) { |
- DCHECK_NE(ui::SCALE_FACTOR_NONE, scale_factor); |
- |
- // Some fields are only relevant for pre-MD vs. MD. Erase the irrelevant ones |
- // so they don't cause incorrect cache misses. |
- // TODO(pkasting): Remove |resource_id| field when non-MD code is deleted. |
- if (ui::MaterialDesignController::IsModeMaterial()) |
- resource_id = 0; |
- else |
- fill_color = stroke_color = SK_ColorTRANSPARENT; |
-} |
- |
-Tab::ImageCacheEntryMetadata::~ImageCacheEntryMetadata() {} |
- |
-bool Tab::ImageCacheEntryMetadata::operator==( |
- const ImageCacheEntryMetadata& rhs) const { |
- return resource_id == rhs.resource_id && fill_color == rhs.fill_color && |
- stroke_color == rhs.stroke_color && scale_factor == rhs.scale_factor && |
- size == rhs.size; |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// Tab::ImageCacheEntry |
- |
-struct Tab::ImageCacheEntry { |
- ImageCacheEntry(const ImageCacheEntryMetadata& metadata, |
- const gfx::ImageSkia& image); |
- ~ImageCacheEntry(); |
- |
- ImageCacheEntryMetadata metadata; |
- gfx::ImageSkia image; |
-}; |
- |
-Tab::ImageCacheEntry::ImageCacheEntry(const ImageCacheEntryMetadata& metadata, |
- const gfx::ImageSkia& image) |
- : metadata(metadata), image(image) {} |
- |
-Tab::ImageCacheEntry::~ImageCacheEntry() {} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// Tab, statics: |
+// Tab, public: |
// static |
const char Tab::kViewClassName[] = "Tab"; |
-Tab::TabImages Tab::active_images_ = {0}; |
-Tab::TabImages Tab::inactive_images_ = {0}; |
-Tab::TabImages Tab::mask_images_ = {0}; |
-Tab::ImageCache* Tab::image_cache_ = NULL; |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// Tab, public: |
Tab::Tab(TabController* controller, gfx::AnimationContainer* container) |
: controller_(controller), |
@@ -810,7 +974,7 @@ bool Tab::GetHitTestMask(gfx::Path* mask) const { |
if (ui::MaterialDesignController::IsModeMaterial()) { |
SkPath border; |
const float scale = GetWidget()->GetCompositor()->device_scale_factor(); |
- GetBorderPath(scale, extend_to_top, &border); |
+ GetBorderPath(scale, size(), extend_to_top, &border); |
mask->addPath(border, SkMatrix::MakeScale(1 / scale)); |
} else { |
// Hit mask constants. |
@@ -1292,16 +1456,16 @@ void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { |
controller_->GetToolbarTopSeparatorColor(), |
ui::GetSupportedScaleFactor(canvas->image_scale()), size()); |
auto it = std::find_if( |
- image_cache_->begin(), image_cache_->end(), |
+ image_cache->begin(), image_cache->end(), |
[&metadata](const ImageCacheEntry& e) { return e.metadata == metadata; }); |
- if (it == image_cache_->end()) { |
+ if (it == image_cache->end()) { |
gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false); |
PaintTabBackgroundUsingFillId(&tmp_canvas, false, fill_id, false, y_offset); |
- image_cache_->emplace_front(metadata, |
- gfx::ImageSkia(tmp_canvas.ExtractImageRep())); |
- if (image_cache_->size() > kMaxImageCacheSize) |
- image_cache_->pop_back(); |
- it = image_cache_->begin(); |
+ image_cache->emplace_front(metadata, |
+ gfx::ImageSkia(tmp_canvas.ExtractImageRep())); |
+ if (image_cache->size() > kMaxImageCacheSize) |
+ image_cache->pop_back(); |
+ it = image_cache->begin(); |
} |
canvas->DrawImageInt(it->image, 0, 0); |
} |
@@ -1333,7 +1497,7 @@ void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* canvas, |
// Draw the fill. |
SkPath fill; |
- GetFillPath(scale, &fill); |
+ GetFillPath(scale, size(), &fill); |
SkPaint paint; |
paint.setAntiAlias(true); |
{ |
@@ -1359,7 +1523,7 @@ void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* canvas, |
// Draw the stroke. |
SkPath stroke; |
- GetBorderPath(scale, false, &stroke); |
+ GetBorderPath(scale, size(), false, &stroke); |
Op(stroke, fill, kDifference_SkPathOp, &stroke); |
if (!is_active) { |
// Clip out the bottom line; this will be drawn for us by |
@@ -1374,7 +1538,7 @@ void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* canvas, |
// Draw everything to a temporary canvas so we can extract an image for |
// use in masking the hover glow. |
gfx::Canvas background_canvas(size(), canvas->image_scale(), false); |
- PaintTabFill(&background_canvas, fill_image, x_offset, y_offset, |
+ PaintTabFill(&background_canvas, fill_image, x_offset, y_offset, size(), |
is_active); |
gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); |
canvas->DrawImageInt(background_image, 0, 0); |
@@ -1385,11 +1549,11 @@ void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* canvas, |
gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); |
canvas->DrawImageInt(result, 0, 0); |
} else { |
- PaintTabFill(canvas, fill_image, x_offset, y_offset, is_active); |
+ PaintTabFill(canvas, fill_image, x_offset, y_offset, size(), is_active); |
} |
// Now draw the stroke, highlights, and shadows around the tab edge. |
- TabImages* stroke_images = is_active ? &active_images_ : &inactive_images_; |
+ TabImages* stroke_images = is_active ? &active_images : &inactive_images; |
canvas->DrawImageInt(*stroke_images->image_l, 0, 0); |
canvas->TileImageInt( |
*stroke_images->image_c, stroke_images->l_width, 0, |
@@ -1399,45 +1563,6 @@ void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* canvas, |
} |
} |
-void Tab::PaintTabFill(gfx::Canvas* canvas, |
- gfx::ImageSkia* fill_image, |
- int x_offset, |
- int y_offset, |
- bool is_active) { |
- const gfx::Insets tab_insets(GetLayoutInsets(TAB)); |
- // If this isn't the foreground tab, don't draw over the toolbar, but do |
- // include the 1 px divider stroke at the bottom. |
- const int toolbar_overlap = is_active ? 0 : (tab_insets.bottom() - 1); |
- |
- // Draw left edge. |
- gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( |
- *fill_image, x_offset, y_offset, mask_images_.l_width, height()); |
- gfx::ImageSkia theme_l = |
- gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *mask_images_.image_l); |
- canvas->DrawImageInt( |
- theme_l, 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, 0, 0, |
- theme_l.width(), theme_l.height() - toolbar_overlap, false); |
- |
- // Draw right edge. |
- gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( |
- *fill_image, x_offset + width() - mask_images_.r_width, y_offset, |
- mask_images_.r_width, height()); |
- gfx::ImageSkia theme_r = |
- gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *mask_images_.image_r); |
- canvas->DrawImageInt(theme_r, 0, 0, theme_r.width(), |
- theme_r.height() - toolbar_overlap, |
- width() - theme_r.width(), 0, theme_r.width(), |
- theme_r.height() - toolbar_overlap, false); |
- |
- // Draw center. Instead of masking out the top portion we simply skip over it |
- // by incrementing by the top padding, since it's a simple rectangle. |
- canvas->TileImageInt(*fill_image, x_offset + mask_images_.l_width, |
- y_offset + tab_insets.top(), mask_images_.l_width, |
- tab_insets.top(), |
- width() - mask_images_.l_width - mask_images_.r_width, |
- height() - tab_insets.top() - toolbar_overlap); |
-} |
- |
void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( |
gfx::Canvas* canvas, |
const gfx::Rect& favicon_draw_bounds) { |
@@ -1674,118 +1799,13 @@ void Tab::ScheduleIconPaint() { |
SchedulePaintInRect(bounds); |
} |
-void Tab::GetFillPath(float scale, SkPath* fill) const { |
- const float right = width() * scale; |
- // The bottom of the tab needs to be pixel-aligned or else when we call |
- // ClipPath with anti-aliasing enabled it can cause artifacts. |
- const float bottom = std::ceil(height() * scale); |
- const float unscaled_endcap_width = GetUnscaledEndcapWidth(); |
- |
- fill->moveTo(right - 1, bottom); |
- fill->rCubicTo(-0.75 * scale, 0, -1.625 * scale, -0.5 * scale, -2 * scale, |
- -1.5 * scale); |
- fill->lineTo(right - 1 - (unscaled_endcap_width - 2) * scale, 2.5 * scale); |
- // Prevent overdraw in the center near minimum width (only happens if |
- // scale < 2). We could instead avoid this by increasing the tab inset |
- // values, but that would shift all the content inward as well, unless we |
- // then overlapped the content on the endcaps, by which point we'd have a |
- // huge mess. |
- const float scaled_endcap_width = 1 + unscaled_endcap_width * scale; |
- const float overlap = scaled_endcap_width * 2 - right; |
- const float offset = (overlap > 0) ? (overlap / 2) : 0; |
- fill->rCubicTo(-0.375 * scale, -1 * scale, -1.25 * scale + offset, |
- -1.5 * scale, -2 * scale + offset, -1.5 * scale); |
- if (overlap < 0) |
- fill->lineTo(scaled_endcap_width, scale); |
- fill->rCubicTo(-0.75 * scale, 0, -1.625 * scale - offset, 0.5 * scale, |
- -2 * scale - offset, 1.5 * scale); |
- fill->lineTo(1 + 2 * scale, bottom - 1.5 * scale); |
- fill->rCubicTo(-0.375 * scale, scale, -1.25 * scale, 1.5 * scale, -2 * scale, |
- 1.5 * scale); |
- fill->close(); |
-} |
- |
-void Tab::GetBorderPath(float scale, bool extend_to_top, SkPath* path) const { |
- const float top = scale - 1; |
- const float right = width() * scale; |
- const float bottom = height() * scale; |
- const float unscaled_endcap_width = GetUnscaledEndcapWidth(); |
- |
- path->moveTo(0, bottom); |
- path->rLineTo(0, -1); |
- path->rCubicTo(0.75 * scale, 0, 1.625 * scale, -0.5 * scale, 2 * scale, |
- -1.5 * scale); |
- path->lineTo((unscaled_endcap_width - 2) * scale, top + 1.5 * scale); |
- if (extend_to_top) { |
- // Create the vertical extension by extending the side diagonals until they |
- // reach the top of the bounds. |
- const float dy = 2.5 * scale - 1; |
- const float dx = GetInverseDiagonalSlope() * dy; |
- path->rLineTo(dx, -dy); |
- path->lineTo(right - (unscaled_endcap_width - 2) * scale - dx, 0); |
- path->rLineTo(dx, dy); |
- } else { |
- path->rCubicTo(0.375 * scale, -scale, 1.25 * scale, -1.5 * scale, 2 * scale, |
- -1.5 * scale); |
- path->lineTo(right - unscaled_endcap_width * scale, top); |
- path->rCubicTo(0.75 * scale, 0, 1.625 * scale, 0.5 * scale, 2 * scale, |
- 1.5 * scale); |
- } |
- path->lineTo(right - 2 * scale, bottom - 1 - 1.5 * scale); |
- path->rCubicTo(0.375 * scale, scale, 1.25 * scale, 1.5 * scale, 2 * scale, |
- 1.5 * scale); |
- path->rLineTo(0, 1); |
- path->close(); |
-} |
- |
gfx::Rect Tab::GetImmersiveBarRect() const { |
// The main bar is as wide as the normal tab's horizontal top line. |
// This top line of the tab extends a few pixels left and right of the |
// center image due to pixels in the rounded corner images. |
const int kBarPadding = 1; |
- int main_bar_left = active_images_.l_width - kBarPadding; |
- int main_bar_right = width() - active_images_.r_width + kBarPadding; |
+ int main_bar_left = active_images.l_width - kBarPadding; |
+ int main_bar_right = width() - active_images.r_width + kBarPadding; |
return gfx::Rect( |
main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight); |
} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// Tab, private static: |
- |
-// static |
-void Tab::InitTabResources() { |
- static bool initialized = false; |
- if (initialized) |
- return; |
- |
- initialized = true; |
- image_cache_ = new ImageCache(); |
- |
- // Load the tab images once now, and maybe again later if the theme changes. |
- LoadTabImages(); |
-} |
- |
-// static |
-void Tab::LoadTabImages() { |
- image_cache_->clear(); |
- |
- // We're not letting people override tab images just yet. |
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
- |
- active_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_LEFT); |
- active_images_.image_c = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_CENTER); |
- active_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_RIGHT); |
- active_images_.l_width = active_images_.image_l->width(); |
- active_images_.r_width = active_images_.image_r->width(); |
- |
- inactive_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_LEFT); |
- inactive_images_.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); |
- inactive_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); |
- inactive_images_.l_width = inactive_images_.image_l->width(); |
- inactive_images_.r_width = inactive_images_.image_r->width(); |
- |
- mask_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); |
- mask_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); |
- mask_images_.l_width = mask_images_.image_l->width(); |
- mask_images_.r_width = mask_images_.image_r->width(); |
-} |