1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
|
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/chrome_typography_provider.h"
#include "chrome/browser/ui/views/chrome_typography.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/platform_font.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/view.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#include "ui/gfx/platform_font_win.h"
#include "ui/native_theme/native_theme_win.h"
#endif
#if defined(OS_CHROMEOS)
// gn check complains on Linux Ozone.
#include "ash/public/cpp/ash_typography.h" // nogncheck
#endif
namespace {
// If the default foreground color from the native theme isn't black, the rest
// of the Harmony spec isn't going to work. Also skip Harmony if a Windows
// High Contrast theme is enabled. One of the four standard High Contrast themes
// in Windows 10 still has black text, but (since the user wants high contrast)
// the grey text shades in Harmony should not be used.
bool ShouldIgnoreHarmonySpec(const ui::NativeTheme& theme) {
if (theme.UsesHighContrastColors())
return true;
constexpr auto kTestColorId = ui::NativeTheme::kColorId_LabelEnabledColor;
return theme.GetSystemColor(kTestColorId) != SK_ColorBLACK;
}
// Returns a color for a possibly inverted or high-contrast OS color theme.
SkColor GetHarmonyTextColorForNonStandardNativeTheme(
int context,
int style,
const ui::NativeTheme& theme) {
// At the time of writing, very few UI surfaces need typography for a Chrome-
// provided theme. Typically just incognito browser windows (when the native
// theme is NativeThemeDarkAura). Instead, this method is consulted when the
// actual OS theme is configured in a special way. So pick from a small number
// of NativeTheme constants that are known to adapt properly to distinct
// colors when configuring the OS to use a high-contrast theme. For example,
// ::GetSysColor() on Windows has 8 text colors: BTNTEXT, CAPTIONTEXT,
// GRAYTEXT, HIGHLIGHTTEXT, INACTIVECAPTIONTEXT, INFOTEXT (tool tips),
// MENUTEXT, and WINDOWTEXT. There's also hyperlinks: COLOR_HOTLIGHT.
// Diverging from these risks using a color that doesn't match user
// expectations.
const bool inverted_scheme = color_utils::IsInvertedColorScheme();
ui::NativeTheme::ColorId color_id =
(context == views::style::CONTEXT_BUTTON ||
context == views::style::CONTEXT_BUTTON_MD)
? ui::NativeTheme::kColorId_ButtonEnabledColor
: ui::NativeTheme::kColorId_TextfieldDefaultColor;
switch (style) {
case views::style::STYLE_DIALOG_BUTTON_DEFAULT:
// This is just white in Harmony and, even in inverted themes, prominent
// buttons have a dark background, so white will maximize contrast.
return SK_ColorWHITE;
case views::style::STYLE_DISABLED:
color_id = ui::NativeTheme::kColorId_LabelDisabledColor;
break;
case views::style::STYLE_LINK:
color_id = ui::NativeTheme::kColorId_LinkEnabled;
break;
case STYLE_RED:
return inverted_scheme ? gfx::kGoogleRed300 : gfx::kGoogleRed600;
case STYLE_GREEN:
return inverted_scheme ? gfx::kGoogleGreen300 : gfx::kGoogleGreen600;
}
return theme.GetSystemColor(color_id);
}
} // namespace
#if defined(OS_WIN)
// static
int ChromeTypographyProvider::GetPlatformFontHeight(int font_context) {
const bool direct_write_enabled =
gfx::PlatformFontWin::IsDirectWriteEnabled();
const bool windows_10 = base::win::GetVersion() >= base::win::VERSION_WIN10;
switch (font_context) {
case CONTEXT_HEADLINE:
return windows_10 && direct_write_enabled ? 27 : 28;
case views::style::CONTEXT_DIALOG_TITLE:
return windows_10 || !direct_write_enabled ? 20 : 21;
case CONTEXT_BODY_TEXT_LARGE:
case views::style::CONTEXT_MESSAGE_BOX_BODY_TEXT:
return direct_write_enabled ? 18 : 17;
case CONTEXT_BODY_TEXT_SMALL:
return windows_10 && direct_write_enabled ? 16 : 15;
}
NOTREACHED();
return 0;
}
#endif
const gfx::FontList& ChromeTypographyProvider::GetFont(int context,
int style) const {
// "Target" font size constants from the Harmony spec.
constexpr int kHeadlineSize = 20;
constexpr int kTitleSize = 15;
constexpr int kBodyTextLargeSize = 13;
constexpr int kDefaultSize = 12;
int size_delta = kDefaultSize - gfx::PlatformFont::kDefaultBaseFontSize;
gfx::Font::Weight font_weight = gfx::Font::Weight::NORMAL;
#if defined(OS_CHROMEOS)
ash::ApplyAshFontStyles(context, style, &size_delta, &font_weight);
#endif
ApplyCommonFontStyles(context, style, &size_delta, &font_weight);
switch (context) {
case views::style::CONTEXT_BUTTON_MD:
font_weight = MediumWeightForUI();
break;
case views::style::CONTEXT_DIALOG_TITLE:
size_delta = kTitleSize - gfx::PlatformFont::kDefaultBaseFontSize;
break;
case CONTEXT_BODY_TEXT_LARGE:
case views::style::CONTEXT_MESSAGE_BOX_BODY_TEXT:
size_delta = kBodyTextLargeSize - gfx::PlatformFont::kDefaultBaseFontSize;
break;
case CONTEXT_HEADLINE:
size_delta = kHeadlineSize - gfx::PlatformFont::kDefaultBaseFontSize;
break;
default:
break;
}
// Use a bold style for emphasized text in body contexts, and ignore |style|
// otherwise.
if (style == STYLE_EMPHASIZED || style == STYLE_EMPHASIZED_SECONDARY) {
switch (context) {
case CONTEXT_BODY_TEXT_SMALL:
case CONTEXT_BODY_TEXT_LARGE:
case views::style::CONTEXT_MESSAGE_BOX_BODY_TEXT:
font_weight = gfx::Font::Weight::BOLD;
break;
default:
break;
}
}
return ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta(
size_delta, gfx::Font::NORMAL, font_weight);
}
SkColor ChromeTypographyProvider::GetColor(const views::View& view,
int context,
int style) const {
const ui::NativeTheme* native_theme = view.GetNativeTheme();
DCHECK(native_theme);
if (ShouldIgnoreHarmonySpec(*native_theme)) {
return GetHarmonyTextColorForNonStandardNativeTheme(context, style,
*native_theme);
}
if (context == views::style::CONTEXT_BUTTON_MD) {
switch (style) {
case views::style::STYLE_DIALOG_BUTTON_DEFAULT:
return SK_ColorWHITE;
case views::style::STYLE_DISABLED:
return SkColorSetRGB(0x9e, 0x9e, 0x9e);
default:
return SkColorSetRGB(0x75, 0x75, 0x75);
}
}
// Use the secondary style instead of primary for message box body text.
if (context == views::style::CONTEXT_MESSAGE_BOX_BODY_TEXT &&
style == views::style::STYLE_PRIMARY) {
style = STYLE_SECONDARY;
}
switch (style) {
case views::style::STYLE_DIALOG_BUTTON_DEFAULT:
return SK_ColorWHITE;
case views::style::STYLE_DISABLED:
return SkColorSetRGB(0x9e, 0x9e, 0x9e);
case views::style::STYLE_LINK:
return gfx::kGoogleBlue700;
case STYLE_SECONDARY:
case STYLE_EMPHASIZED_SECONDARY:
case STYLE_HINT:
return gfx::kGoogleGrey700;
case STYLE_RED:
return gfx::kGoogleRed700;
case STYLE_GREEN:
return gfx::kGoogleGreen700;
}
// Use GoogleGrey900 as primary color for everything else.
return gfx::kGoogleGrey900;
}
int ChromeTypographyProvider::GetLineHeight(int context, int style) const {
// "Target" line height constants from the Harmony spec. A default OS
// configuration should use these heights. However, if the user overrides OS
// defaults, then GetLineHeight() should return the height that would add the
// same extra space between lines as the default configuration would have.
constexpr int kHeadlineHeight = 32;
constexpr int kTitleHeight = 22;
constexpr int kBodyHeight = 20; // For both large and small.
// Button text should always use the minimum line height for a font to avoid
// unnecessarily influencing the height of a button.
constexpr int kButtonAbsoluteHeight = 0;
// The platform-specific heights (i.e. gfx::Font::GetHeight()) that result when
// asking for the target size constants in ChromeTypographyProvider::GetFont()
// in a default OS configuration.
#if defined(OS_MACOSX)
constexpr int kHeadlinePlatformHeight = 25;
constexpr int kTitlePlatformHeight = 19;
constexpr int kBodyTextLargePlatformHeight = 16;
constexpr int kBodyTextSmallPlatformHeight = 15;
#elif defined(OS_WIN)
static const int kHeadlinePlatformHeight =
GetPlatformFontHeight(CONTEXT_HEADLINE);
static const int kTitlePlatformHeight =
GetPlatformFontHeight(views::style::CONTEXT_DIALOG_TITLE);
static const int kBodyTextLargePlatformHeight =
GetPlatformFontHeight(CONTEXT_BODY_TEXT_LARGE);
static const int kBodyTextSmallPlatformHeight =
GetPlatformFontHeight(CONTEXT_BODY_TEXT_SMALL);
#else
constexpr int kHeadlinePlatformHeight = 24;
constexpr int kTitlePlatformHeight = 18;
constexpr int kBodyTextLargePlatformHeight = 17;
constexpr int kBodyTextSmallPlatformHeight = 15;
#endif
// The style of the system font used to determine line heights.
constexpr int kTemplateStyle = views::style::STYLE_PRIMARY;
// TODO(tapted): These statics should be cleared out when something invokes
// ui::ResourceBundle::ReloadFonts(). Currently that only happens on ChromeOS.
// See http://crbug.com/708943.
static const int headline_height =
GetFont(CONTEXT_HEADLINE, kTemplateStyle).GetHeight() -
kHeadlinePlatformHeight + kHeadlineHeight;
static const int title_height =
GetFont(views::style::CONTEXT_DIALOG_TITLE, kTemplateStyle).GetHeight() -
kTitlePlatformHeight + kTitleHeight;
static const int body_large_height =
GetFont(CONTEXT_BODY_TEXT_LARGE, kTemplateStyle).GetHeight() -
kBodyTextLargePlatformHeight + kBodyHeight;
static const int default_height =
GetFont(CONTEXT_BODY_TEXT_SMALL, kTemplateStyle).GetHeight() -
kBodyTextSmallPlatformHeight + kBodyHeight;
switch (context) {
case views::style::CONTEXT_BUTTON:
case views::style::CONTEXT_BUTTON_MD:
case CONTEXT_TOOLBAR_BUTTON:
return kButtonAbsoluteHeight;
case views::style::CONTEXT_DIALOG_TITLE:
return title_height;
case CONTEXT_BODY_TEXT_LARGE:
case views::style::CONTEXT_MESSAGE_BOX_BODY_TEXT:
case views::style::CONTEXT_TABLE_ROW:
return body_large_height;
case CONTEXT_HEADLINE:
return headline_height;
default:
return default_height;
}
}
|