| // Copyright 2017 The Chromium Authors |
| // 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 "build/build_config.h" |
| #include "chrome/browser/ui/color/chrome_color_id.h" |
| #include "chrome/browser/ui/views/chrome_typography.h" |
| #include "ui/base/default_style.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/base/theme_provider.h" |
| #include "ui/color/color_id.h" |
| #include "ui/gfx/color_palette.h" |
| #include "ui/gfx/color_utils.h" |
| #include "ui/gfx/platform_font.h" |
| #include "ui/views/style/typography.h" |
| |
| #if BUILDFLAG(IS_WIN) |
| #include "base/win/windows_version.h" |
| #include "ui/native_theme/native_theme_win.h" |
| #endif |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| #include <optional> |
| |
| // gn check complains on Linux Ozone. |
| #include "ash/public/cpp/ash_typography.h" // nogncheck |
| #endif |
| |
| bool ChromeTypographyProvider::StyleAllowedForContext(int context, |
| int style) const { |
| if (context == CONTEXT_TAB_HOVER_CARD_TITLE) { |
| return style == views::style::STYLE_PRIMARY || |
| style == views::style::STYLE_BODY_3_EMPHASIS; |
| } |
| |
| if (style == views::style::STYLE_EMPHASIZED || |
| style == views::style::STYLE_EMPHASIZED_SECONDARY) { |
| // Limit emphasizing text to contexts where it's obviously correct. If you |
| // hit this check, ensure it's sane and UX-approved to extend it to your |
| // new case (e.g. don't add CONTEXT_BUTTON_MD). |
| #if BUILDFLAG(IS_CHROMEOS) |
| // TODO(crbug.com/40234831): Limit more specific Ash contexts. |
| return true; |
| #else |
| return context == views::style::CONTEXT_LABEL || |
| context == views::style::CONTEXT_DIALOG_BODY_TEXT || |
| context == CONTEXT_DIALOG_BODY_TEXT_SMALL; |
| #endif |
| } |
| |
| return TypographyProvider::StyleAllowedForContext(context, style); |
| } |
| |
| ui::ResourceBundle::FontDetails ChromeTypographyProvider::GetFontDetailsImpl( |
| int context, |
| int style) const { |
| if (style > views::style::STYLE_OVERRIDE_TYPOGRAPHY_START && |
| style < views::style::STYLE_OVERRIDE_TYPOGRAPHY_END) { |
| return TypographyProvider::GetFontDetailsImpl(context, style); |
| } |
| |
| // "Target" font size constants. |
| constexpr int kTitleSize = 15; |
| constexpr int kTouchableLabelSize = 14; |
| constexpr int kBodyTextLargeSize = 13; |
| constexpr int kCR23ButtonTextSize = 13; |
| constexpr int kDefaultSize = 12; |
| constexpr int kBadgeSize = 9; |
| |
| ui::ResourceBundle::FontDetails details; |
| |
| details.size_delta = gfx::PlatformFont::GetFontSizeDelta(kDefaultSize); |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| ash::ApplyAshFontStyles(context, style, details); |
| #endif |
| |
| ApplyCommonFontStyles(context, style, details); |
| |
| switch (context) { |
| case views::style::CONTEXT_BADGE: |
| details.size_delta = gfx::PlatformFont::GetFontSizeDelta(kBadgeSize); |
| details.weight = gfx::Font::Weight::BOLD; |
| break; |
| case views::style::CONTEXT_BUTTON_MD: |
| details.weight = MediumWeightForUI(); |
| details.size_delta = |
| gfx::PlatformFont::GetFontSizeDelta(kCR23ButtonTextSize); |
| break; |
| case views::style::CONTEXT_DIALOG_TITLE: |
| details.size_delta = gfx::PlatformFont::GetFontSizeDelta(kTitleSize); |
| break; |
| case views::style::CONTEXT_TOUCH_MENU: |
| details.size_delta = |
| gfx::PlatformFont::GetFontSizeDelta(kTouchableLabelSize); |
| break; |
| case views::style::CONTEXT_DIALOG_BODY_TEXT: |
| case CONTEXT_TAB_HOVER_CARD_TITLE: |
| details.size_delta = |
| gfx::PlatformFont::GetFontSizeDelta(kBodyTextLargeSize); |
| break; |
| default: |
| break; |
| } |
| |
| if (context == CONTEXT_TAB_HOVER_CARD_TITLE) { |
| details.weight = gfx::Font::Weight::SEMIBOLD; |
| } |
| |
| if (context == CONTEXT_TAB_COUNTER && |
| style == views::style::STYLE_SECONDARY) { |
| // Secondary font is for double-digit counts. Because we have control over |
| // system fonts on ChromeOS, we can just choose a condensed font. For other |
| // platforms we adjust size. |
| #if BUILDFLAG(IS_CHROMEOS) |
| details.typeface = "Roboto Condensed"; |
| #else |
| details.size_delta -= 2; |
| #endif |
| } |
| |
| if (style == views::style::STYLE_EMPHASIZED || |
| style == views::style::STYLE_EMPHASIZED_SECONDARY) { |
| details.weight = gfx::Font::Weight::SEMIBOLD; |
| } |
| |
| if (style == views::style::STYLE_PRIMARY_MONOSPACED || |
| style == views::style::STYLE_SECONDARY_MONOSPACED) { |
| #if BUILDFLAG(IS_MAC) |
| details.typeface = "Menlo"; |
| #elif BUILDFLAG(IS_WIN) |
| details.typeface = "Consolas"; |
| #else |
| details.typeface = "DejaVu Sans Mono"; |
| #endif |
| } |
| |
| if (style == STYLE_SMALL) { |
| details.size_delta -= 2; |
| } |
| |
| return details; |
| } |
| |
| ui::ColorId ChromeTypographyProvider::GetColorIdImpl(int context, |
| int style) const { |
| #if BUILDFLAG(IS_CHROMEOS) |
| // TODO(crbug.com/400615941): Remove ash-spcecific handling from //chrome. |
| if (std::optional<ui::ColorId> color_id = ash::GetColorId(style); |
| color_id.has_value()) { |
| return color_id.value(); |
| } |
| #endif |
| |
| // Body text styles are the same as for labels. |
| if (context == views::style::CONTEXT_DIALOG_BODY_TEXT || |
| context == CONTEXT_DIALOG_BODY_TEXT_SMALL) { |
| context = views::style::CONTEXT_LABEL; |
| } |
| |
| // Monospaced styles have the same colors as their normal counterparts. |
| if (style == views::style::STYLE_PRIMARY_MONOSPACED) { |
| style = views::style::STYLE_PRIMARY; |
| } else if (style == views::style::STYLE_SECONDARY_MONOSPACED) { |
| style = views::style::STYLE_SECONDARY; |
| } |
| |
| switch (style) { |
| case STYLE_RED: |
| return ui::kColorAlertHighSeverity; |
| case STYLE_GREEN: |
| return ui::kColorAlertLowSeverity; |
| default: |
| return TypographyProvider::GetColorIdImpl(context, style); |
| } |
| } |
| |
| int ChromeTypographyProvider::GetLineHeightImpl(int context, int style) const { |
| if (style > views::style::STYLE_OVERRIDE_TYPOGRAPHY_START && |
| style < views::style::STYLE_OVERRIDE_TYPOGRAPHY_END) { |
| return TypographyProvider::GetLineHeightImpl(context, style); |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| // TODO(crbug.com/400615941): Remove ash-spcecific handling when we remove |
| // usage where GetLineHeightImpl receives ash-specific `context`. |
| std::optional<int> height = ash::GetLineHeight(context); |
| if (height) { |
| return height.value(); |
| } |
| #endif |
| |
| // "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 kTitleHeight = 22; |
| constexpr int kBodyHeight = 20; // For both large and small. |
| constexpr int kControlHeight = 16; |
| |
| // 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 BUILDFLAG(IS_MAC) |
| constexpr int kTitlePlatformHeight = 19; |
| constexpr int kBodyTextLargePlatformHeight = 16; |
| constexpr int kBodyTextSmallPlatformHeight = 15; |
| #elif BUILDFLAG(IS_WIN) |
| constexpr int kTitlePlatformHeight = 20; |
| constexpr int kBodyTextLargePlatformHeight = 18; |
| constexpr int kBodyTextSmallPlatformHeight = 16; |
| #else |
| 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 title_height = |
| GetFont(views::style::CONTEXT_DIALOG_TITLE, kTemplateStyle).GetHeight() - |
| kTitlePlatformHeight + kTitleHeight; |
| static const int body_large_height = |
| GetFont(views::style::CONTEXT_DIALOG_BODY_TEXT, kTemplateStyle) |
| .GetHeight() - |
| kBodyTextLargePlatformHeight + kBodyHeight; |
| static const int control_height = |
| GetFont(CONTEXT_DIALOG_BODY_TEXT_SMALL, kTemplateStyle).GetHeight() - |
| kBodyTextSmallPlatformHeight + kControlHeight; |
| static const int default_height = |
| GetFont(CONTEXT_DIALOG_BODY_TEXT_SMALL, kTemplateStyle).GetHeight() - |
| kBodyTextSmallPlatformHeight + kBodyHeight; |
| |
| switch (context) { |
| case views::style::CONTEXT_BUTTON: |
| case views::style::CONTEXT_BUTTON_MD: |
| case views::style::CONTEXT_TEXTFIELD: |
| case CONTEXT_TOOLBAR_BUTTON: |
| return control_height; |
| case views::style::CONTEXT_DIALOG_TITLE: |
| return title_height; |
| case views::style::CONTEXT_DIALOG_BODY_TEXT: |
| case views::style::CONTEXT_TABLE_ROW: |
| case CONTEXT_TAB_HOVER_CARD_TITLE: |
| return body_large_height; |
| default: |
| return default_height; |
| } |
| } |