| 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 90d920f8597577eec5f15674290b36c4e1b04d36..d0e2138483633f7b62009d81834dc7299bd1b65d 100644
|
| --- a/chrome/browser/ui/views/tabs/tab.cc
|
| +++ b/chrome/browser/ui/views/tabs/tab.cc
|
| @@ -44,6 +44,7 @@
|
| #include "ui/gfx/color_analysis.h"
|
| #include "ui/gfx/favicon_size.h"
|
| #include "ui/gfx/geometry/rect_conversions.h"
|
| +#include "ui/gfx/image/canvas_image_source.h"
|
| #include "ui/gfx/image/image_skia_operations.h"
|
| #include "ui/gfx/paint_vector_icon.h"
|
| #include "ui/gfx/path.h"
|
| @@ -121,32 +122,93 @@ const double kDesaturateHue = -1.0;
|
| const double kDesaturateSaturation = 0.0;
|
| const double kDesaturateLightness = 0.6;
|
|
|
| -// Parameters for PaintTabBackgroundUsingParams().
|
| +// Parameters for PaintTabFill/StrokeUsingParams().
|
| struct PaintBackgroundParams {
|
| PaintBackgroundParams(bool is_active,
|
| - gfx::ImageSkia* fill_image_ptr,
|
| + gfx::ImageSkia* fill_image,
|
| bool has_custom_image,
|
| - gfx::Rect rect,
|
| + const gfx::Rect& rect,
|
| SkColor stroke_color,
|
| SkColor toolbar_color,
|
| - SkColor background_tab_color)
|
| + SkColor background_tab_color,
|
| + bool draw_hover,
|
| + const gfx::Point& hover_location,
|
| + SkAlpha hover_alpha)
|
| : is_active(is_active),
|
| - fill_image(fill_image_ptr ? *fill_image_ptr : gfx::ImageSkia()),
|
| - has_custom_image(has_custom_image),
|
| + fill_image(fill_image ? *fill_image : gfx::ImageSkia()),
|
| rect(rect),
|
| stroke_color(stroke_color),
|
| toolbar_color(toolbar_color),
|
| - background_tab_color(background_tab_color) {}
|
| + background_tab_color(background_tab_color),
|
| + draw_hover(draw_hover),
|
| + hover_location(PointToSkPoint(hover_location)),
|
| + hover_alpha(hover_alpha) {}
|
|
|
| const bool is_active;
|
| const gfx::ImageSkia fill_image;
|
| - const bool has_custom_image;
|
| const gfx::Rect rect;
|
| const SkColor stroke_color;
|
| const SkColor toolbar_color;
|
| const SkColor background_tab_color;
|
| + const bool draw_hover;
|
| + const SkPoint hover_location;
|
| + const SkAlpha hover_alpha;
|
| };
|
|
|
| +void PaintTabFillUsingParams(gfx::Canvas* canvas,
|
| + const PaintBackgroundParams& params);
|
| +
|
| +void PaintTabStrokeUsingParams(gfx::Canvas* canvas,
|
| + const PaintBackgroundParams& params);
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// TabImageSource
|
| +//
|
| +// This subclass of CanvasImageSource allows the inactive tab image to be cached
|
| +// once for each requested scale factor.
|
| +class TabImageSource : public gfx::CanvasImageSource {
|
| + public:
|
| + enum UseCanvas { FILL, STROKE, BOTH };
|
| +
|
| + TabImageSource(UseCanvas use_canvas, Tab* tab, int fill_id, int y_offset);
|
| + ~TabImageSource() override {}
|
| +
|
| + // gfx::CanvasImageSource override.
|
| + void Draw(gfx::Canvas* canvas) override;
|
| + bool HasRepresentationAtAllScales() const override { return true; }
|
| +
|
| + private:
|
| + const UseCanvas use_canvas_;
|
| + const PaintBackgroundParams params_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TabImageSource);
|
| +};
|
| +
|
| +TabImageSource::TabImageSource(UseCanvas use_canvas,
|
| + Tab* tab,
|
| + int fill_id,
|
| + int y_offset)
|
| + : gfx::CanvasImageSource(tab->size(), true),
|
| + use_canvas_(use_canvas),
|
| + params_(false,
|
| + tab->GetThemeProvider()->GetImageSkiaNamed(fill_id),
|
| + false,
|
| + gfx::Rect(gfx::Point(0, y_offset), tab->size()),
|
| + tab->controller()->GetToolbarTopSeparatorColor(),
|
| + tab->GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR),
|
| + tab->GetThemeProvider()->GetColor(
|
| + ThemeProperties::COLOR_BACKGROUND_TAB),
|
| + false,
|
| + gfx::Point(),
|
| + 255) {}
|
| +
|
| +void TabImageSource::Draw(gfx::Canvas* canvas) {
|
| + if (use_canvas_ != STROKE)
|
| + PaintTabFillUsingParams(canvas, params_);
|
| + if (use_canvas_ != FILL)
|
| + PaintTabStrokeUsingParams(canvas, params_);
|
| +}
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // ImageCacheEntryMetadata
|
| //
|
| @@ -156,7 +218,6 @@ struct ImageCacheEntryMetadata {
|
| SkColor fill_color,
|
| SkColor stroke_color,
|
| bool use_fill_and_stroke_images,
|
| - ui::ScaleFactor scale_factor,
|
| const gfx::Size& size);
|
|
|
| ~ImageCacheEntryMetadata();
|
| @@ -167,7 +228,6 @@ struct ImageCacheEntryMetadata {
|
| SkColor fill_color; // Both colors only needed by MD
|
| SkColor stroke_color;
|
| bool use_fill_and_stroke_images;
|
| - ui::ScaleFactor scale_factor;
|
| gfx::Size size;
|
| };
|
|
|
| @@ -176,16 +236,12 @@ ImageCacheEntryMetadata::ImageCacheEntryMetadata(
|
| SkColor fill_color,
|
| SkColor stroke_color,
|
| bool use_fill_and_stroke_images,
|
| - ui::ScaleFactor scale_factor,
|
| const gfx::Size& size)
|
| : resource_id(resource_id),
|
| fill_color(fill_color),
|
| stroke_color(stroke_color),
|
| use_fill_and_stroke_images(use_fill_and_stroke_images),
|
| - 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.
|
| @@ -202,7 +258,7 @@ bool ImageCacheEntryMetadata::operator==(
|
| return resource_id == rhs.resource_id && 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;
|
| + size == rhs.size;
|
| }
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
| @@ -211,8 +267,9 @@ bool ImageCacheEntryMetadata::operator==(
|
| // 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);
|
| + Tab* tab,
|
| + int fill_id,
|
| + int y_offset);
|
| ~ImageCacheEntry();
|
|
|
| ImageCacheEntryMetadata metadata;
|
| @@ -221,9 +278,21 @@ struct ImageCacheEntry {
|
| };
|
|
|
| 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) {}
|
| + Tab* tab,
|
| + int fill_id,
|
| + int y_offset)
|
| + : metadata(metadata) {
|
| + if (metadata.use_fill_and_stroke_images) {
|
| + fill_image = gfx::ImageSkia(
|
| + new TabImageSource(TabImageSource::FILL, tab, fill_id, y_offset),
|
| + tab->size());
|
| + }
|
| + TabImageSource::UseCanvas use = metadata.use_fill_and_stroke_images
|
| + ? TabImageSource::STROKE
|
| + : TabImageSource::BOTH;
|
| + stroke_image = gfx::ImageSkia(new TabImageSource(use, tab, fill_id, y_offset),
|
| + tab->size());
|
| +}
|
|
|
| ImageCacheEntry::~ImageCacheEntry() {}
|
|
|
| @@ -486,73 +555,45 @@ void PaintTabFill(gfx::Canvas* canvas,
|
| tab_insets.top(), rect.width(), rect.height());
|
| }
|
|
|
| -void PaintTabBackgroundUsingParams(gfx::Canvas* fill_canvas,
|
| - gfx::Canvas* stroke_canvas,
|
| - views::GlowHoverController* hc,
|
| - const PaintBackgroundParams& params) {
|
| +// In non-MD mode, there is never a need to draw fill and stroke onto separate
|
| +// canvases, so in that case, this function does both.
|
| +void PaintTabFillUsingParams(gfx::Canvas* canvas,
|
| + const PaintBackgroundParams& params) {
|
| const gfx::Rect& rect = params.rect;
|
| const SkScalar kMinHoverRadius = 16;
|
| const SkScalar radius =
|
| std::max(SkFloatToScalar(rect.width() / 4.f), kMinHoverRadius);
|
| - const bool draw_hover = !params.is_active && hc;
|
| - SkPoint hover_location(
|
| - gfx::PointToSkPoint(draw_hover ? hc->location() : gfx::Point()));
|
| const SkColor hover_color =
|
| - SkColorSetA(params.toolbar_color, draw_hover ? hc->GetAlpha() : 255);
|
| + SkColorSetA(params.toolbar_color, params.hover_alpha);
|
|
|
| if (ui::MaterialDesignController::IsModeMaterial()) {
|
| - gfx::Path fill;
|
| - SkPaint paint;
|
| - paint.setAntiAlias(true);
|
| + gfx::ScopedCanvas scoped_canvas(canvas);
|
| + const float scale = canvas->UndoDeviceScaleFactor();
|
| + gfx::Path fill = GetFillPath(scale, rect.size());
|
|
|
| - // Draw the fill.
|
| {
|
| - gfx::ScopedCanvas scoped_canvas(fill_canvas);
|
| - const float scale = fill_canvas->UndoDeviceScaleFactor();
|
| -
|
| - fill = GetFillPath(scale, rect.size());
|
| - {
|
| - gfx::ScopedCanvas clip_scoper(fill_canvas);
|
| - fill_canvas->ClipPath(fill, true);
|
| - if (!params.fill_image.isNull()) {
|
| - gfx::ScopedCanvas scale_scoper(fill_canvas);
|
| - fill_canvas->sk_canvas()->scale(scale, scale);
|
| - fill_canvas->TileImageInt(params.fill_image, rect.x(), rect.y(), 0, 0,
|
| - rect.width(), rect.height());
|
| - } else {
|
| - paint.setColor(params.is_active ? params.toolbar_color
|
| - : params.background_tab_color);
|
| - fill_canvas->DrawRect(
|
| - gfx::ScaleToEnclosingRect(gfx::Rect(rect.size()), scale),
|
| - paint);
|
| - }
|
| - if (draw_hover) {
|
| - hover_location.scale(SkFloatToScalar(scale));
|
| - DrawHighlight(fill_canvas, hover_location, radius * scale,
|
| - hover_color);
|
| - }
|
| + gfx::ScopedCanvas clip_scoper(canvas);
|
| + canvas->ClipPath(fill, true);
|
| + if (!params.fill_image.isNull()) {
|
| + gfx::ScopedCanvas scale_scoper(canvas);
|
| + canvas->sk_canvas()->scale(scale, scale);
|
| + canvas->TileImageInt(params.fill_image, rect.x(), rect.y(), 0, 0,
|
| + rect.width(), rect.height());
|
| + } else {
|
| + SkPaint paint;
|
| + paint.setAntiAlias(true);
|
| + paint.setColor(params.is_active ? params.toolbar_color
|
| + : params.background_tab_color);
|
| + canvas->DrawRect(
|
| + gfx::ScaleToEnclosingRect(gfx::Rect(rect.size()), scale), paint);
|
| }
|
| - }
|
| -
|
| - // Draw the stroke.
|
| - {
|
| - gfx::ScopedCanvas scoped_canvas(stroke_canvas);
|
| - const float scale = stroke_canvas->UndoDeviceScaleFactor();
|
| -
|
| - gfx::Path stroke = GetBorderPath(scale, false, false, rect.size());
|
| - Op(stroke, fill, kDifference_SkPathOp, &stroke);
|
| - if (!params.is_active) {
|
| - // Clip out the bottom line; this will be drawn for us by
|
| - // TabStrip::PaintChildren().
|
| - stroke_canvas->ClipRect(gfx::RectF(rect.width() * scale,
|
| - rect.height() * scale - 1));
|
| + if (params.draw_hover) {
|
| + DrawHighlight(canvas, params.hover_location * scale, radius * scale,
|
| + hover_color);
|
| }
|
| - paint.setColor(params.stroke_color);
|
| - stroke_canvas->DrawPath(stroke, paint);
|
| }
|
| } else {
|
| - gfx::Canvas* canvas = stroke_canvas;
|
| - if (draw_hover) {
|
| + if (params.draw_hover) {
|
| // Draw everything to a temporary canvas so we can extract an image for
|
| // use in masking the hover glow.
|
| gfx::Canvas background_canvas(rect.size(), canvas->image_scale(), false);
|
| @@ -562,7 +603,7 @@ void PaintTabBackgroundUsingParams(gfx::Canvas* fill_canvas,
|
| canvas->DrawImageInt(background_image, 0, 0);
|
|
|
| gfx::Canvas hover_canvas(rect.size(), canvas->image_scale(), false);
|
| - DrawHighlight(&hover_canvas, hover_location, radius, hover_color);
|
| + DrawHighlight(&hover_canvas, params.hover_location, radius, hover_color);
|
| gfx::ImageSkia result = gfx::ImageSkiaOperations::CreateMaskedImage(
|
| gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image);
|
| canvas->DrawImageInt(result, 0, 0);
|
| @@ -583,6 +624,27 @@ void PaintTabBackgroundUsingParams(gfx::Canvas* fill_canvas,
|
| }
|
| }
|
|
|
| +void PaintTabStrokeUsingParams(gfx::Canvas* canvas,
|
| + const PaintBackgroundParams& params) {
|
| + DCHECK(ui::MaterialDesignController::IsModeMaterial());
|
| + gfx::ScopedCanvas scoped_canvas(canvas);
|
| + const float scale = canvas->UndoDeviceScaleFactor();
|
| +
|
| + SkPaint paint;
|
| + paint.setAntiAlias(true);
|
| + gfx::Path stroke = GetBorderPath(scale, false, false, params.rect.size());
|
| + gfx::Path fill = GetFillPath(scale, params.rect.size());
|
| + Op(stroke, fill, kDifference_SkPathOp, &stroke);
|
| + if (!params.is_active) {
|
| + // Clip out the bottom line; this will be drawn for us by
|
| + // TabStrip::PaintChildren().
|
| + canvas->ClipRect(gfx::RectF(params.rect.width() * scale,
|
| + params.rect.height() * scale - 1));
|
| + }
|
| + paint.setColor(params.stroke_color);
|
| + canvas->DrawPath(stroke, paint);
|
| +}
|
| +
|
| // Desaturates the favicon. Should only be used for when a tab encounters a
|
| // network error state.
|
| void PaintDesaturatedFavIcon(gfx::Canvas* canvas,
|
| @@ -1452,7 +1514,7 @@ void Tab::PaintTab(gfx::Canvas* canvas, const gfx::Path& clip) {
|
| GetThemeProvider()->HasCustomImage(kActiveTabFillId);
|
| const int y_offset = -GetYInsetForActiveTabBackground();
|
| if (IsActive()) {
|
| - PaintTabBackgroundUsingFillId(canvas, canvas, true, kActiveTabFillId,
|
| + PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId,
|
| has_custom_image, y_offset);
|
| } else {
|
| PaintInactiveTabBackground(canvas, clip);
|
| @@ -1461,7 +1523,7 @@ 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,
|
| + PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId,
|
| has_custom_image, y_offset);
|
| canvas->Restore();
|
| }
|
| @@ -1532,8 +1594,8 @@ void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas,
|
| // 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 || hover_controller_.ShouldDraw()) {
|
| - PaintTabBackgroundUsingFillId(canvas, canvas, false, fill_id,
|
| - has_custom_image, y_offset);
|
| + PaintTabBackgroundUsingFillId(canvas, false, fill_id, has_custom_image,
|
| + y_offset);
|
| return;
|
| }
|
|
|
| @@ -1548,26 +1610,12 @@ void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas,
|
| const ImageCacheEntryMetadata metadata(
|
| fill_id, tp->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB),
|
| controller_->GetToolbarTopSeparatorColor(), use_fill_and_stroke_images,
|
| - ui::GetSupportedScaleFactor(canvas->image_scale()), size());
|
| + 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,
|
| - fill_id, false, y_offset);
|
| - g_image_cache->emplace_front(
|
| - metadata, gfx::ImageSkia(tmp_fill_canvas.ExtractImageRep()),
|
| - gfx::ImageSkia(tmp_canvas.ExtractImageRep()));
|
| - } else {
|
| - PaintTabBackgroundUsingFillId(&tmp_canvas, &tmp_canvas, false, fill_id,
|
| - false, y_offset);
|
| - g_image_cache->emplace_front(
|
| - metadata, gfx::ImageSkia(),
|
| - gfx::ImageSkia(tmp_canvas.ExtractImageRep()));
|
| - }
|
| + g_image_cache->emplace_front(metadata, this, fill_id, y_offset);
|
| if (g_image_cache->size() > kMaxImageCacheSize)
|
| g_image_cache->pop_back();
|
| it = g_image_cache->begin();
|
| @@ -1582,14 +1630,11 @@ void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas,
|
| canvas->DrawImageInt(it->stroke_image, 0, 0);
|
| }
|
|
|
| -void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* fill_canvas,
|
| - gfx::Canvas* stroke_canvas,
|
| +void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* canvas,
|
| bool is_active,
|
| int fill_id,
|
| bool has_custom_image,
|
| int y_offset) {
|
| - views::GlowHoverController* hc =
|
| - hover_controller_.ShouldDraw() ? &hover_controller_ : nullptr;
|
| gfx::ImageSkia* fill_image =
|
| has_custom_image || !ui::MaterialDesignController::IsModeMaterial()
|
| ? GetThemeProvider()->GetImageSkiaNamed(fill_id)
|
| @@ -1603,9 +1648,12 @@ void Tab::PaintTabBackgroundUsingFillId(gfx::Canvas* fill_canvas,
|
| is_active, fill_image, has_custom_image, rect,
|
| controller_->GetToolbarTopSeparatorColor(),
|
| GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR),
|
| - GetThemeProvider()->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB));
|
| + GetThemeProvider()->GetColor(ThemeProperties::COLOR_BACKGROUND_TAB),
|
| + !is_active && hover_controller_.ShouldDraw(),
|
| + hover_controller_.location(), hover_controller_.GetAlpha());
|
|
|
| - PaintTabBackgroundUsingParams(fill_canvas, stroke_canvas, hc, params);
|
| + PaintTabFillUsingParams(canvas, params);
|
| + PaintTabStrokeUsingParams(canvas, params);
|
| }
|
|
|
| void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon(
|
|
|