blob: 8b2584189cfe65ecbcd96b97129e662e445ad249 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/badge_painter.h"
#include <algorithm>
#include "base/i18n/rtl.h"
#include "ui/base/ui_base_features.h"
#include "ui/color/color_id.h"
#include "ui/color/color_provider.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/text_constants.h"
#include "ui/gfx/text_utils.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/style/typography.h"
#include "ui/views/style/typography_provider.h"
#include "ui/views/view.h"
namespace views {
namespace {
// Returns the highlight rect for the badge given the font and text rect
// for the badge text.
gfx::Rect GetBadgeRectOutsetAroundText(const gfx::FontList& badge_font,
const gfx::Rect& badge_text_rect) {
gfx::Rect badge_rect = badge_text_rect;
badge_rect.Inset(-gfx::AdjustVisualBorderForFont(
badge_font, gfx::Insets(BadgePainter::kBadgeInternalPadding)));
return badge_rect;
}
} // namespace
// static
void BadgePainter::PaintBadge(gfx::Canvas* canvas,
const View* view,
int unmirrored_badge_left_x,
int text_top_y,
const std::u16string& text,
const gfx::FontList& primary_font) {
gfx::FontList badge_font = GetBadgeFont(primary_font);
// Calculate bounding box for badge text.
unmirrored_badge_left_x += kBadgeInternalPadding;
text_top_y += gfx::GetFontCapHeightCenterOffset(primary_font, badge_font);
gfx::Rect badge_text_bounds(gfx::Point(unmirrored_badge_left_x, text_top_y),
gfx::GetStringSize(text, badge_font));
if (base::i18n::IsRTL()) {
badge_text_bounds.set_x(view->GetMirroredXForRect(badge_text_bounds));
}
// Render the badge itself.
cc::PaintFlags flags;
const ui::ColorProvider* color_provider = view->GetColorProvider();
const SkColor background_color =
color_provider->GetColor(ui::kColorBadgeBackground);
flags.setColor(background_color);
canvas->DrawRoundRect(
GetBadgeRectOutsetAroundText(badge_font, badge_text_bounds),
LayoutProvider::Get()->GetCornerRadiusMetric(
ShapeContextTokens::kBadgeRadius),
flags);
// Render the badge text.
const SkColor foreground_color =
color_provider->GetColor(ui::kColorBadgeForeground);
canvas->DrawStringRect(text, badge_font, foreground_color, badge_text_bounds);
}
// static
gfx::Size BadgePainter::GetBadgeSize(const std::u16string& text,
const gfx::FontList& primary_font) {
gfx::FontList badge_font = GetBadgeFont(primary_font);
const gfx::Size text_size = gfx::GetStringSize(text, badge_font);
return GetBadgeRectOutsetAroundText(badge_font, gfx::Rect(text_size)).size();
}
gfx::FontList BadgePainter::GetBadgeFont(const gfx::FontList& context_font) {
if (features::IsChromeRefresh2023()) {
return views::TypographyProvider::Get().GetFont(
views::style::CONTEXT_BADGE, views::style::STYLE_SECONDARY);
}
// Preferred font is slightly smaller and slightly more bold than the title
// font. The size change is required to make it look correct in the badge; we
// add a small degree of bold to prevent color smearing/blurring due to font
// smoothing. This ensures readability on all platforms and in both light and
// dark modes.
return context_font.Derive(BadgePainter::kBadgeFontSizeAdjustment,
gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM);
}
} // namespace views