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

Unified Diff: chrome/browser/ui/views/tabs/tab.cc

Issue 2803583003: ui: Remove use of bitmaps when painting tab backgrounds. (Closed)
Patch Set: tabbackground: . 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 side-by-side diff with in-line comments
Download patch
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 2ffdb637649a0ae160fef1571625e00f30de891b..a759053dc9ef6e86bb823fe7cda6c8f9212e6a64 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -14,7 +14,7 @@
#include "base/metrics/user_metrics.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
-#include "cc/paint/paint_shader.h"
+#include "cc/paint/paint_flags.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/browser.h"
@@ -93,95 +93,9 @@ const double kSelectedTabOpacity = 0.3;
// Inactive selected tabs have their throb value scaled by this.
const double kSelectedTabThrobScale = 0.95 - kSelectedTabOpacity;
-// Max number of images to cache. This has to be at least two since rounding
-// errors may lead to tabs in the same tabstrip having different sizes.
-// 8 = normal/incognito, active/inactive, 2 sizes within tabstrip.
-const size_t kMaxImageCacheSize = 8;
-
const char kTabCloseButtonName[] = "TabCloseButton";
////////////////////////////////////////////////////////////////////////////////
-// ImageCacheEntryMetadata
-//
-// All metadata necessary to uniquely identify a cached image.
-struct ImageCacheEntryMetadata {
- ImageCacheEntryMetadata(SkColor fill_color,
- SkColor stroke_color,
- bool use_fill_and_stroke_images,
- float scale_factor,
- const gfx::Size& size);
-
- ~ImageCacheEntryMetadata();
-
- bool operator==(const ImageCacheEntryMetadata& rhs) const;
-
- SkColor fill_color;
- SkColor stroke_color;
- bool use_fill_and_stroke_images;
- float scale_factor;
- gfx::Size size;
-};
-
-ImageCacheEntryMetadata::ImageCacheEntryMetadata(
- SkColor fill_color,
- SkColor stroke_color,
- bool use_fill_and_stroke_images,
- float scale_factor,
- const gfx::Size& size)
- : fill_color(fill_color),
- stroke_color(stroke_color),
- use_fill_and_stroke_images(use_fill_and_stroke_images),
- scale_factor(scale_factor),
- size(size) {}
-
-ImageCacheEntryMetadata::~ImageCacheEntryMetadata() {}
-
-bool ImageCacheEntryMetadata::operator==(
- const ImageCacheEntryMetadata& rhs) const {
- return fill_color == rhs.fill_color && stroke_color == rhs.stroke_color &&
- use_fill_and_stroke_images == rhs.use_fill_and_stroke_images &&
- 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& fill_image,
- const gfx::ImageSkia& stroke_image);
- ~ImageCacheEntry();
-
- ImageCacheEntryMetadata metadata;
- gfx::ImageSkia fill_image;
- gfx::ImageSkia stroke_image;
-};
-
-ImageCacheEntry::ImageCacheEntry(const ImageCacheEntryMetadata& metadata,
- const gfx::ImageSkia& fill_image,
- const gfx::ImageSkia& stroke_image)
- : metadata(metadata), fill_image(fill_image), stroke_image(stroke_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* g_image_cache = nullptr;
-
-// Performs a one-time initialization of static resources such as tab images.
-void InitTabResources() {
- static bool initialized = false;
- if (initialized)
- return;
-
- initialized = true;
- g_image_cache = new ImageCache();
-}
-
-////////////////////////////////////////////////////////////////////////////////
// Drawing and utility functions
// Returns the width of the tab endcap at scale 1. More precisely, this is the
@@ -534,7 +448,6 @@ Tab::Tab(TabController* controller, gfx::AnimationContainer* container)
showing_close_button_(false),
button_color_(SK_ColorTRANSPARENT) {
DCHECK(controller);
- InitTabResources();
// So we get don't get enter/exit on children and don't prematurely stop the
// hover.
@@ -1123,8 +1036,9 @@ void Tab::PaintTab(gfx::Canvas* canvas, const gfx::Path& clip) {
: 0;
const int y_offset = -GetLayoutInsets(TAB).top();
if (IsActive()) {
- PaintTabBackgroundUsingFillId(canvas, canvas, true, kActiveTabFillId,
- y_offset);
+ bool active = true;
+ gfx::Path* no_clip = nullptr;
+ PaintTabBackground(canvas, active, kActiveTabFillId, y_offset, no_clip);
} else {
PaintInactiveTabBackground(canvas, clip);
@@ -1132,8 +1046,9 @@ void Tab::PaintTab(gfx::Canvas* canvas, const gfx::Path& clip) {
if (throb_value > 0) {
canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff),
GetLocalBounds());
- PaintTabBackgroundUsingFillId(canvas, canvas, true, kActiveTabFillId,
- y_offset);
+ bool active = true;
+ gfx::Path* no_clip = nullptr;
+ PaintTabBackground(canvas, active, kActiveTabFillId, y_offset, no_clip);
canvas->Restore();
}
}
@@ -1145,131 +1060,106 @@ void Tab::PaintTab(gfx::Canvas* canvas, const gfx::Path& clip) {
void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas,
const gfx::Path& clip) {
bool has_custom_image;
- int fill_id = controller_->GetBackgroundResourceId(&has_custom_image);
- const ui::ThemeProvider* tp = GetThemeProvider();
+ int background_resource_id =
+ controller_->GetBackgroundResourceId(&has_custom_image);
+
+ int fill_id = 0;
+ int y_offset = 0;
+ bool may_clip = controller_->MaySetClip();
- // We only cache the image when it's the default image and we're not hovered,
- // to avoid caching a background image that isn't the same for all tabs.
if (has_custom_image) {
+ const ui::ThemeProvider* tp = GetThemeProvider();
+
// If the theme is providing a custom background image, then its top edge
// should be at the top of the tab. Otherwise, we assume that the background
// image is a composited foreground + frame image. Note that if the theme
// is only providing a custom frame image, |has_custom_image| will be true,
// but we should use the |background_offset_| here.
- const int y_offset =
- tp->HasCustomImage(fill_id) ? 0 : background_offset_.y();
- PaintTabBackgroundUsingFillId(canvas, canvas, false, fill_id, y_offset);
- return;
- }
- if (hover_controller_.ShouldDraw()) {
- PaintTabBackgroundUsingFillId(canvas, canvas, false, 0, 0);
- return;
+ fill_id = background_resource_id;
+ y_offset =
+ tp->HasCustomImage(background_resource_id) ? 0 : background_offset_.y();
+ may_clip = false;
}
- // For efficiency, we don't use separate fill and stroke images unless we
- // really need to clip the stroke and not the fill (for stacked tabs). This
- // saves memory and avoids an extra image draw at the cost of recalculating
- // the images when MaySetClip() toggles.
- const bool use_fill_and_stroke_images = controller_->MaySetClip();
-
- const ImageCacheEntryMetadata metadata(
- tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB),
- controller_->GetToolbarTopSeparatorColor(), use_fill_and_stroke_images,
- canvas->image_scale(), size());
- auto it = std::find_if(
- g_image_cache->begin(), g_image_cache->end(),
- [&metadata](const ImageCacheEntry& e) { return e.metadata == metadata; });
- if (it == g_image_cache->end()) {
- gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false);
- if (use_fill_and_stroke_images) {
- gfx::Canvas tmp_fill_canvas(size(), canvas->image_scale(), false);
- PaintTabBackgroundUsingFillId(&tmp_fill_canvas, &tmp_canvas, false, 0, 0);
- g_image_cache->emplace_front(
- metadata, gfx::ImageSkia(tmp_fill_canvas.ExtractImageRep()),
- gfx::ImageSkia(tmp_canvas.ExtractImageRep()));
- } else {
- PaintTabBackgroundUsingFillId(&tmp_canvas, &tmp_canvas, false, 0, 0);
- g_image_cache->emplace_front(
- metadata, gfx::ImageSkia(),
- gfx::ImageSkia(tmp_canvas.ExtractImageRep()));
+ bool active = false;
+ PaintTabBackground(canvas, active, fill_id, y_offset,
+ may_clip ? clip : nullptr);
+}
+
+void Tab::PaintTabBackground(gfx::Canvas* canvas,
+ bool active,
+ int fill_id,
+ int y_offset,
+ const gfx::Path* clip) {
+ gfx::Path fill_path = GetFillPath(canvas->image_scale(), size());
+
+ PaintTabBackgroundFill(canvas, fill_path, active, fill_id, y_offset);
+ {
+ base::Optional<gfx::ScopedCanvas> scoped_canvas;
+ if (clip) {
+ scoped_canvas.emplace(canvas);
+ canvas->sk_canvas()->clipPath(*clip, SkClipOp::kDifference, true);
}
- if (g_image_cache->size() > kMaxImageCacheSize)
- g_image_cache->pop_back();
- it = g_image_cache->begin();
+ PaintTabBackgroundStroke(canvas, fill_path, active);
}
+}
- gfx::ScopedCanvas scoped_canvas(
- use_fill_and_stroke_images ? canvas : nullptr);
- if (use_fill_and_stroke_images) {
- canvas->DrawImageInt(it->fill_image, 0, 0);
- canvas->sk_canvas()->clipPath(clip, SkClipOp::kDifference, true);
+void Tab::PaintTabBackgroundFill(gfx::Canvas* canvas,
+ const gfx::Path& fill_path,
+ bool active,
+ int fill_id,
+ int y_offset) {
+ const ui::ThemeProvider* tp = GetThemeProvider();
+ SkColor active_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR);
+ SkColor inactive_color = tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB);
+
+ gfx::ScopedCanvas scoped_canvas(canvas);
+ const float scale = canvas->UndoDeviceScaleFactor();
+
+ canvas->ClipPath(fill_path, true);
+ if (fill_id) {
+ gfx::ScopedCanvas scale_scoper(canvas);
+ canvas->sk_canvas()->scale(scale, scale);
+ canvas->TileImageInt(*tp->GetImageSkiaNamed(fill_id),
+ GetMirroredX() + background_offset_.x(), y_offset, 0,
+ 0, width(), height());
+ } else {
+ cc::PaintFlags flags;
+ flags.setAntiAlias(true);
+ flags.setColor(active ? active_color : inactive_color);
+ canvas->DrawRect(gfx::ScaleToEnclosingRect(GetLocalBounds(), scale), flags);
}
- canvas->DrawImageInt(it->stroke_image, 0, 0);
-}
-void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* fill_canvas,
- gfx::Canvas* stroke_canvas,
- bool is_active,
- int fill_id,
- int y_offset) {
- gfx::Path fill;
- cc::PaintFlags flags;
- flags.setAntiAlias(true);
+ if (!active && hover_controller_.ShouldDraw()) {
+ SkPoint hover_location(gfx::PointToSkPoint(hover_controller_.location()));
+ hover_location.scale(SkFloatToScalar(scale));
+ const SkScalar kMinHoverRadius = 16;
+ const SkScalar radius =
+ std::max(SkFloatToScalar(width() / 4.f), kMinHoverRadius);
+ DrawHighlight(canvas, hover_location, radius * scale,
+ SkColorSetA(active_color, hover_controller_.GetAlpha()));
+ }
+}
- // Draw the fill.
- {
- gfx::ScopedCanvas scoped_canvas(fill_canvas);
- const float scale = fill_canvas->UndoDeviceScaleFactor();
- const ui::ThemeProvider* tp = GetThemeProvider();
- const SkColor toolbar_color = tp->GetColor(ThemeProperties::COLOR_TOOLBAR);
-
- fill = GetFillPath(scale, size());
- {
- gfx::ScopedCanvas clip_scoper(fill_canvas);
- fill_canvas->ClipPath(fill, true);
- if (fill_id) {
- gfx::ScopedCanvas scale_scoper(fill_canvas);
- fill_canvas->sk_canvas()->scale(scale, scale);
- fill_canvas->TileImageInt(*tp->GetImageSkiaNamed(fill_id),
- GetMirroredX() + background_offset_.x(),
- y_offset, 0, 0, width(), height());
- } else {
- flags.setColor(
- is_active ? toolbar_color
- : tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB));
- fill_canvas->DrawRect(
- gfx::ScaleToEnclosingRect(GetLocalBounds(), scale), flags);
- }
+void Tab::PaintTabBackgroundStroke(gfx::Canvas* canvas,
+ const gfx::Path& fill_path,
+ bool active) {
+ SkColor color = controller_->GetToolbarTopSeparatorColor();
- if (!is_active && hover_controller_.ShouldDraw()) {
- SkPoint hover_location(
- gfx::PointToSkPoint(hover_controller_.location()));
- hover_location.scale(SkFloatToScalar(scale));
- const SkScalar kMinHoverRadius = 16;
- const SkScalar radius =
- std::max(SkFloatToScalar(width() / 4.f), kMinHoverRadius);
- DrawHighlight(fill_canvas, hover_location, radius * scale,
- SkColorSetA(toolbar_color, hover_controller_.GetAlpha()));
- }
- }
- }
+ gfx::ScopedCanvas scoped_canvas(canvas);
+ const float scale = canvas->UndoDeviceScaleFactor();
- // Draw the stroke.
- {
- gfx::ScopedCanvas scoped_canvas(stroke_canvas);
- const float scale = stroke_canvas->UndoDeviceScaleFactor();
-
- gfx::Path stroke = GetBorderPath(scale, false, false, size());
- Op(stroke, fill, kDifference_SkPathOp, &stroke);
- if (!is_active) {
- // Clip out the bottom line; this will be drawn for us by
- // TabStrip::PaintChildren().
- stroke_canvas->ClipRect(
- gfx::RectF(width() * scale, height() * scale - 1));
- }
- flags.setColor(controller_->GetToolbarTopSeparatorColor());
- stroke_canvas->DrawPath(stroke, flags);
+ gfx::Path stroke = GetBorderPath(scale, false, false, size());
+ Op(stroke, fill_path, kDifference_SkPathOp, &stroke);
+ if (!active) {
+ // Clip out the bottom line; this will be drawn for us by
+ // TabStrip::PaintChildren().
+ canvas->ClipRect(gfx::RectF(width() * scale, height() * scale - 1));
}
+ cc::PaintFlags flags;
+ flags.setAntiAlias(true);
+ flags.setColor(color);
+ canvas->DrawPath(stroke, flags);
}
void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon(

Powered by Google App Engine
This is Rietveld 408576698