Commit 94f04868 authored by Ahmed Fakhry's avatar Ahmed Fakhry Committed by Commit Bot

Fix extensions badges and decorations positions

The extensions browser actions badges and decorations should
be positioned at the corners of the icon area, rather than the
corners of the full button's area (i.e. ignoring the paddings).

Screenshots: https://bugs.chromium.org/p/chromium/issues/detail?id=831946#c11

BUG=831946

Change-Id: I977883a3e6127e1f91779a7e73b4adb7fa7c6471
Reviewed-on: https://chromium-review.googlesource.com/1013290Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Commit-Queue: Ahmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#550855}
parent 43a2ea05
......@@ -12,7 +12,9 @@
#include "build/build_config.h"
#include "cc/paint/paint_flags.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/grit/theme_resources.h"
#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
......@@ -23,13 +25,6 @@
namespace {
const int kPadding = 2;
const int kBadgeHeight = 11;
const int kMaxTextWidth = 23;
// The minimum width for center-aligning the badge.
const int kCenterAlignThreshold = 20;
gfx::ImageSkiaRep ScaleImageSkiaRep(const gfx::ImageSkiaRep& rep,
int target_width_dp,
float target_scale) {
......@@ -41,6 +36,10 @@ gfx::ImageSkiaRep ScaleImageSkiaRep(const gfx::ImageSkiaRep& rep,
target_scale);
}
bool IsTouchOptimized() {
return ui::MaterialDesignController::IsTouchOptimizedUiEnabled();
}
} // namespace
IconWithBadgeImageSource::Badge::Badge(const std::string& text,
......@@ -110,14 +109,15 @@ void IconWithBadgeImageSource::PaintBadge(gfx::Canvas* canvas) {
? gfx::kGoogleBlue500
: SkColorSetA(badge_->background_color, SK_AlphaOPAQUE);
const int badge_height = IsTouchOptimized() ? 12 : 11;
ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
gfx::FontList base_font = rb->GetFontList(ui::ResourceBundle::BaseFont)
.DeriveWithHeightUpperBound(kBadgeHeight);
.DeriveWithHeightUpperBound(badge_height);
base::string16 utf16_text = base::UTF8ToUTF16(badge_->text);
// See if we can squeeze a slightly larger font into the badge given the
// actual string that is to be displayed.
const int kMaxIncrementAttempts = 5;
constexpr int kMaxIncrementAttempts = 5;
for (size_t i = 0; i < kMaxIncrementAttempts; ++i) {
int w = 0;
int h = 0;
......@@ -125,28 +125,37 @@ void IconWithBadgeImageSource::PaintBadge(gfx::Canvas* canvas) {
base_font.Derive(1, 0, gfx::Font::Weight::NORMAL);
gfx::Canvas::SizeStringInt(utf16_text, bigger_font, &w, &h, 0,
gfx::Canvas::NO_ELLIPSIS);
if (h > kBadgeHeight)
if (h > badge_height)
break;
base_font = bigger_font;
}
constexpr int kMaxTextWidth = 23;
const int text_width =
std::min(kMaxTextWidth, canvas->GetStringWidth(utf16_text, base_font));
// Calculate badge size. It is clamped to a min width just because it looks
// silly if it is too skinny.
constexpr int kPadding = 2;
int badge_width = text_width + kPadding * 2;
const gfx::Rect icon_area = GetIconAreaRect();
// Force the pixel width of badge to be either odd (if the icon width is odd)
// or even otherwise. If there is a mismatch you get http://crbug.com/26400.
if (size().width() != 0 && (badge_width % 2 != size().width() % 2))
if (icon_area.width() != 0 && (badge_width % 2 != icon_area.width() % 2))
badge_width += 1;
badge_width = std::max(kBadgeHeight, badge_width);
badge_width = std::max(badge_height, badge_width);
// The minimum width for center-aligning the badge.
constexpr int kCenterAlignThreshold = 20;
// Calculate the badge background rect. It is usually right-aligned, but it
// can also be center-aligned if it is large.
gfx::Rect rect(badge_width >= kCenterAlignThreshold
? (size().width() - badge_width) / 2
: size().width() - badge_width,
size().height() - kBadgeHeight, badge_width, kBadgeHeight);
const int badge_offset_x = badge_width >= kCenterAlignThreshold
? (icon_area.width() - badge_width) / 2
: icon_area.width() - badge_width;
const int badge_offset_y = icon_area.height() - badge_height;
gfx::Rect rect(icon_area.x() + badge_offset_x, icon_area.y() + badge_offset_y,
badge_width, badge_height);
cc::PaintFlags rect_flags;
rect_flags.setStyle(cc::PaintFlags::kFill_Style);
rect_flags.setAntiAlias(true);
......@@ -157,23 +166,29 @@ void IconWithBadgeImageSource::PaintBadge(gfx::Canvas* canvas) {
cutout_rect.Inset(-1, -1);
cc::PaintFlags cutout_flags = rect_flags;
cutout_flags.setBlendMode(SkBlendMode::kClear);
canvas->DrawRoundRect(cutout_rect, 2, cutout_flags);
const int outer_corner_radius = IsTouchOptimized() ? 3 : 2;
canvas->DrawRoundRect(cutout_rect, outer_corner_radius, cutout_flags);
// Paint the backdrop.
canvas->DrawRoundRect(rect, 1, rect_flags);
const int inner_corner_radius = outer_corner_radius - 1;
canvas->DrawRoundRect(rect, inner_corner_radius, rect_flags);
// Paint the text.
rect.Inset(std::max(kPadding, (rect.width() - text_width) / 2),
kBadgeHeight - base_font.GetHeight(), kPadding, 0);
badge_height - base_font.GetHeight(), kPadding, 0);
canvas->DrawStringRect(utf16_text, base_font, text_color, rect);
}
void IconWithBadgeImageSource::PaintPageActionDecoration(gfx::Canvas* canvas) {
static const SkColor decoration_color = SkColorSetARGB(255, 70, 142, 226);
int major_radius = std::ceil(size().width() / 5.0);
int minor_radius = std::ceil(major_radius / 2.0);
gfx::Point center_point(major_radius + 1, size().height() - (major_radius)-1);
const gfx::Rect icon_area = GetIconAreaRect();
const int major_radius = std::ceil(icon_area.width() / 5.0);
const int minor_radius =
IsTouchOptimized() ? major_radius - 1 : std::ceil(major_radius / 2.0);
// This decoration is positioned at the bottom left corner of the icon area.
gfx::Point center_point = icon_area.bottom_left();
center_point.Offset(major_radius + 1, -major_radius - 1);
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
......@@ -190,6 +205,14 @@ void IconWithBadgeImageSource::PaintBlockedActionDecoration(
gfx::ImageSkia img =
*ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
IDR_BLOCKED_EXTENSION_SCRIPT);
canvas->DrawImageInt(img, size().width() - img.width(), 0);
// This decoration is positioned at the top right corner of the icon area.
const gfx::Point top_right = GetIconAreaRect().top_right();
canvas->DrawImageInt(img, top_right.x() - img.width(), top_right.y());
canvas->Restore();
}
gfx::Rect IconWithBadgeImageSource::GetIconAreaRect() const {
gfx::Rect icon_area(size());
icon_area.Inset(GetLayoutInsets(TOOLBAR_ACTION_VIEW));
return icon_area;
}
......@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/image/canvas_image_source.h"
#include "ui/gfx/image/image.h"
......@@ -70,6 +71,13 @@ class IconWithBadgeImageSource : public gfx::CanvasImageSource {
// a blocked action that wants to run.
void PaintBlockedActionDecoration(gfx::Canvas* canvas);
// The toolbar action view may have different values of paddings depending on
// the current material design mode (See ToolbarActionsBar::GetViewSize()). In
// all cases, our badges and decorations should be positions at the corners of
// the area where the icon exists (ignoring all the paddings).
// https://crbug.com/831946.
gfx::Rect GetIconAreaRect() const;
// The base icon to draw.
gfx::Image icon_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment