File: chrome_typography_provider.cc

package info (click to toggle)
chromium-browser 70.0.3538.110-1~deb9u1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 1,619,476 kB
  • sloc: cpp: 13,024,755; ansic: 1,349,823; python: 916,672; xml: 314,489; java: 280,047; asm: 276,936; perl: 75,771; objc: 66,634; sh: 45,860; cs: 28,354; php: 11,064; makefile: 10,911; yacc: 9,109; tcl: 8,403; ruby: 4,065; lex: 1,779; pascal: 1,411; lisp: 1,055; awk: 41; jsp: 39; sed: 17; sql: 3
file content (282 lines) | stat: -rw-r--r-- 10,769 bytes parent folder | download
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;
  }
}