Commit 8abd6839 authored by Dana Fried's avatar Dana Fried Committed by Commit Bot

Consolidate font adjustment into PlatformFontWin.

Also fixes a bug where tooltips in Hindi and other languages that use
custom font sizes would revert when the window DPI changes.

Bug: 888788
Change-Id: I490a425d7bf142ef385462837680dfb34f5ff544
Reviewed-on: https://chromium-review.googlesource.com/1250211Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarRobert Liao <robliao@chromium.org>
Commit-Queue: Dana Fried <dfried@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596275}
parent 2b798e97
......@@ -110,9 +110,10 @@ void DumpHungRendererProcessImpl(const base::Process& renderer) {
}
// gfx::Font callbacks
void AdjustUIFont(LOGFONT* logfont) {
display::win::AdjustFontForAccessibility(logfont);
l10n_util::AdjustUIFont(logfont);
void AdjustUIFont(gfx::PlatformFontWin::FontAdjustment* font_adjustment) {
l10n_util::NeedOverrideDefaultUIFont(&font_adjustment->font_family_override,
&font_adjustment->font_scale);
font_adjustment->font_scale *= display::win::GetAccessibilityFontScale();
}
int GetMinimumFontSize() {
......
......@@ -808,7 +808,6 @@ test("ui_base_unittests") {
"clipboard/clipboard_util_mac_unittest.mm",
"l10n/l10n_util_mac_unittest.mm",
"l10n/l10n_util_unittest.cc",
"l10n/l10n_util_win_unittest.cc",
"l10n/time_format_unittest.cc",
"layout_unittest.cc",
"material_design/material_design_controller_unittest.cc",
......
......@@ -4,7 +4,6 @@
#include "ui/base/l10n/l10n_util_win.h"
#include <windowsx.h>
#include <algorithm>
#include <iterator>
......@@ -22,30 +21,6 @@
namespace {
void AdjustLogFont(const base::string16& font_family,
double font_size_scaler,
double dpi_scale,
LOGFONT* logfont) {
DCHECK(font_size_scaler > 0);
font_size_scaler = std::max(std::min(font_size_scaler, 2.0), 0.7);
// Font metrics are computed in pixels and scale in high-DPI mode.
// Normalized by the DPI scale factor in order to work in DIP with
// Views/Aura. Call with dpi_scale=1 to keep the size in pixels.
font_size_scaler /= dpi_scale;
logfont->lfHeight = static_cast<long>(font_size_scaler *
static_cast<double>(abs(logfont->lfHeight)) + 0.5) *
(logfont->lfHeight > 0 ? 1 : -1);
// TODO(jungshik): We may want to check the existence of the font.
// If it's not installed, we shouldn't adjust the font.
if (font_family != L"default") {
int name_len = std::min(static_cast<int>(font_family.size()),
LF_FACESIZE -1);
memcpy(logfont->lfFaceName, font_family.data(), name_len * sizeof(WORD));
logfont->lfFaceName[name_len] = 0;
}
}
class OverrideLocaleHolder {
public:
OverrideLocaleHolder() {}
......@@ -113,44 +88,14 @@ bool NeedOverrideDefaultUIFont(base::string16* override_font_family,
if ((ui_font_family == L"default" && scaler100 == 100) ||
ui_font_family.empty())
return false;
if (override_font_family && font_size_scaler) {
if (override_font_family && ui_font_family != L"default")
override_font_family->swap(ui_font_family);
if (font_size_scaler)
*font_size_scaler = scaler100 / 100.0;
}
return true;
}
void AdjustUIFont(LOGFONT* logfont) {
// Use the unforced scale so the font will be normalized to the correct DIP
// value. That way it'll appear the right size when the forced scale is
// applied later (when coverting to pixels).
AdjustUIFontForDIP(display::win::ScreenWin::GetSystemScaleFactor(), logfont);
}
void AdjustUIFontForDIP(float dpi_scale, LOGFONT* logfont) {
base::string16 ui_font_family = L"default";
double ui_font_size_scaler = 1;
if (NeedOverrideDefaultUIFont(&ui_font_family, &ui_font_size_scaler) ||
dpi_scale != 1) {
AdjustLogFont(ui_font_family, ui_font_size_scaler, dpi_scale, logfont);
}
}
void AdjustUIFontForWindow(HWND hwnd) {
base::string16 ui_font_family;
double ui_font_size_scaler;
if (NeedOverrideDefaultUIFont(&ui_font_family, &ui_font_size_scaler)) {
LOGFONT logfont;
if (GetObject(GetWindowFont(hwnd), sizeof(logfont), &logfont)) {
double dpi_scale = 1;
AdjustLogFont(ui_font_family, ui_font_size_scaler, dpi_scale, &logfont);
HFONT hfont = CreateFontIndirect(&logfont);
if (hfont)
SetWindowFont(hwnd, hfont, FALSE);
}
}
}
void OverrideLocaleWithUILanguageList() {
std::vector<base::string16> ui_languages;
if (base::win::i18n::GetThreadPreferredUILanguageList(&ui_languages)) {
......
......@@ -44,25 +44,6 @@ UI_BASE_EXPORT bool NeedOverrideDefaultUIFont(
base::string16* override_font_family,
double* font_size_scaler);
// If the default UI font stored in |logfont| is not suitable, its family
// and size are replaced with those stored in the per-locale resource. The
// font size is adjusted based on the font scale setting in the OS preferences.
// Windows 8 supports scale factors of 1, 1.4 and 1.8.
UI_BASE_EXPORT void AdjustUIFont(LOGFONT* logfont);
// If the default UI font stored in |logfont| is not suitable, its family
// and size are replaced with those stored in the per-locale resource. The
// |dpi_scale| is the ratio of the OS setting for dots per inch relative to the
// baseline of 96 DPI. This ratio is also used for converting sizes from
// device independent pixels (DIP) to physical pixels. The font size is scaled
// for use with Views and Aura which work in DIP.
UI_BASE_EXPORT void AdjustUIFontForDIP(float dpi_scale, LOGFONT* logfont);
// If the font for a given window (pointed to by HWND) is not suitable for the
// UI in the current UI langauge, its family and size are replaced with those
// stored in the per-locale resource.
UI_BASE_EXPORT void AdjustUIFontForWindow(HWND hwnd);
// Allow processes to override the configured locale with the user's Windows UI
// languages. This function should generally be called once early in
// Application startup.
......
// Copyright (c) 2013 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 "ui/base/l10n/l10n_util_win.h"
#include <windows.h>
#include "base/command_line.h"
#include "base/win/win_client_metrics.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "ui/display/display.h"
#include "ui/display/display_switches.h"
#include "ui/display/win/screen_win.h"
typedef PlatformTest L10nUtilWinTest;
TEST_F(L10nUtilWinTest, TestDPIScaling) {
// Baseline font for comparison.
NONCLIENTMETRICS_XP metrics;
base::win::GetNonClientMetrics(&metrics);
LOGFONT lf = metrics.lfMessageFont;
l10n_util::AdjustUIFont(&lf);
int size = lf.lfHeight;
float rounding = size < 0 ? -0.5f : 0.5f;
// Test that font size is properly normalized for DIP. In high-DPI mode, the
// font metrics are scaled based on the DPI scale factor. For Windows 8, 140%
// and 180% font scaling are supported. Simulate size normalization for a DPI-
// aware process by manually scaling up the font and checking that it returns
// to the expected size.
lf.lfHeight = static_cast<int>(1.4 * size + rounding);
l10n_util::AdjustUIFontForDIP(1.4f, &lf);
EXPECT_NEAR(size, lf.lfHeight, 1);
lf.lfHeight = static_cast<int>(1.8 * size + rounding);
l10n_util::AdjustUIFontForDIP(1.8f, &lf);
EXPECT_NEAR(size, lf.lfHeight, 1);
}
// Test for crbug.com/675933. Since font size is a Windows metric we need to
// normalize to DIPs based on the real device scale factor, not the forced one.
TEST_F(L10nUtilWinTest, TestForcedScaling) {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kForceDeviceScaleFactor, "4");
display::Display::ResetForceDeviceScaleFactorForTesting();
NONCLIENTMETRICS_XP metrics;
base::win::GetNonClientMetrics(&metrics);
LOGFONT lf = metrics.lfMessageFont;
// Set the font size to an arbitrary value and make sure it comes through
// correctly on the other end.
constexpr int test_font_size = 18;
lf.lfHeight = test_font_size;
l10n_util::AdjustUIFont(&lf);
EXPECT_EQ(test_font_size / display::win::ScreenWin::GetSystemScaleFactor(),
lf.lfHeight);
}
......@@ -4,6 +4,8 @@
#include "ui/display/win/dpi.h"
#include <windows.h>
#include "base/win/scoped_hdc.h"
#include "ui/display/display.h"
#include "ui/display/win/uwp_text_scale_factor.h"
......@@ -17,19 +19,6 @@ const float kDefaultDPI = 96.f;
float g_device_scale_factor = 0.f;
LONG AdjustForScaleFactor(LONG value, float scale) {
// This should never happen, but make sure we never divide by zero.
DCHECK_GT(scale, 0.0f);
if (value != 0) {
LONG new_value = LONG{std::roundf(value / scale)};
if (new_value == 0) {
new_value = value > 0 ? 1 : -1;
}
value = new_value;
}
return value;
}
} // namespace
void SetDefaultDeviceScaleFactor(float scale) {
......@@ -47,13 +36,8 @@ int GetDPIFromScalingFactor(float device_scaling_factor) {
return kDefaultDPI * device_scaling_factor;
}
void AdjustFontForAccessibility(LOGFONT* font) {
const float accessibility_scale_factor =
UwpTextScaleFactor::Instance()->GetTextScaleFactor();
font->lfHeight =
AdjustForScaleFactor(font->lfHeight, accessibility_scale_factor);
font->lfWidth =
AdjustForScaleFactor(font->lfWidth, accessibility_scale_factor);
double GetAccessibilityFontScale() {
return 1.0 / UwpTextScaleFactor::Instance()->GetTextScaleFactor();
}
namespace internal {
......
......@@ -5,8 +5,6 @@
#ifndef UI_DISPLAY_WIN_DPI_H_
#define UI_DISPLAY_WIN_DPI_H_
#include <windows.h>
#include "ui/display/display_export.h"
namespace display {
......@@ -29,15 +27,17 @@ DISPLAY_EXPORT float GetDPIScale();
// Returns the equivalent DPI for |device_scaling_factor|.
DISPLAY_EXPORT int GetDPIFromScalingFactor(float device_scaling_factor);
// Adjusts |font|'s height for accessibility measures already built into the
// font in order to prevent applying the same factor twice.
// Returns a factor to adjust a system font's height by, to adjust for
// accessibility measures already built into the font, in order to prevent
// applying the same scale factor twice. Value should be in the range
// 0.0 (exclusive) to 1.0 (inclusive).
//
// Windows will add text scaling factor into the logical size of its default
// system fonts (which it does *not* do for DPI scaling). Since we're scaling
// the entire UI by a combination of text scale and DPI scale, this results in
// double scaling. Call this function to unscale the font before using it in
// any of our rendering code.
DISPLAY_EXPORT void AdjustFontForAccessibility(LOGFONT* font);
DISPLAY_EXPORT double GetAccessibilityFontScale();
namespace internal {
// Note: These methods do not take accessibility adjustments into account.
......
......@@ -4,12 +4,12 @@
#include "ui/gfx/platform_font_win.h"
#include <windows.h>
#include <dwrite.h>
#include <limits.h>
#include <math.h>
#include <stdint.h>
#include <wchar.h>
#include <windows.h>
#include <wrl/client.h>
#include <algorithm>
......@@ -38,36 +38,6 @@
namespace {
gfx::PlatformFontWin::AdjustFontCallback g_adjust_font_callback = nullptr;
gfx::PlatformFontWin::GetMinimumFontSizeCallback
g_get_minimum_font_size_callback = nullptr;
// Returns the minimum font size, using the minimum size callback, if set.
int GetMinimumFontSize() {
int min_font_size = 0;
if (g_get_minimum_font_size_callback)
min_font_size = g_get_minimum_font_size_callback();
return min_font_size;
}
// Returns either minimum font allowed for a current locale or
// lf_height + size_delta value.
int AdjustFontSize(int lf_height, int size_delta) {
if (lf_height < 0) {
lf_height -= size_delta;
} else {
lf_height += size_delta;
}
const int min_font_size = GetMinimumFontSize();
// Make sure lf_height is not smaller than allowed min font size for current
// locale.
if (abs(lf_height) < min_font_size) {
return lf_height < 0 ? -min_font_size : min_font_size;
} else {
return lf_height;
}
}
// Sets style properties on |font_info| based on |font_style|.
void SetLogFontStyle(int font_style, LOGFONT* font_info) {
font_info->lfUnderline = (font_style & gfx::Font::UNDERLINE) != 0;
......@@ -254,6 +224,12 @@ HRESULT GetMatchingDirectWriteFont(LOGFONT* font_info,
return hr;
}
} // namespace
namespace gfx {
namespace internal {
class SystemFonts {
public:
SystemFonts() {
......@@ -289,12 +265,20 @@ class SystemFonts {
private:
void AddFont(gfx::PlatformFontWin::SystemFont system_font, LOGFONT* logfont) {
if (g_adjust_font_callback)
g_adjust_font_callback(logfont);
logfont->lfHeight = AdjustFontSize(logfont->lfHeight, 0);
// Make adjustments to the font as necessary.
if (PlatformFontWin::adjust_font_callback_) {
gfx::PlatformFontWin::FontAdjustment font_adjustment;
PlatformFontWin::adjust_font_callback_(&font_adjustment);
PlatformFontWin::AdjustLOGFONT(font_adjustment, logfont);
}
// Cap at minimum font size.
logfont->lfHeight = PlatformFontWin::AdjustFontSize(logfont->lfHeight, 0);
// Create the Font object.
HFONT font = CreateFontIndirect(logfont);
DLOG_ASSERT(font);
system_fonts_.emplace(system_font, gfx::Font(font));
system_fonts_.emplace(system_font, gfx::PlatformFontWin::HFontToFont(font));
}
// Use a flat map for faster lookups.
......@@ -308,13 +292,19 @@ class SystemFonts {
// static
bool SystemFonts::is_initialized_ = false;
} // namespace
namespace gfx {
} // namespace internal
// static
PlatformFontWin::HFontRef* PlatformFontWin::base_font_ref_;
// static
gfx::PlatformFontWin::AdjustFontCallback
PlatformFontWin::adjust_font_callback_ = nullptr;
// static
gfx::PlatformFontWin::GetMinimumFontSizeCallback
PlatformFontWin::get_minimum_font_size_callback_ = nullptr;
IDWriteFactory* PlatformFontWin::direct_write_factory_ = nullptr;
// TODO(ananta)
......@@ -361,14 +351,14 @@ PlatformFontWin::PlatformFontWin(const std::string& font_name,
// static
void PlatformFontWin::SetGetMinimumFontSizeCallback(
GetMinimumFontSizeCallback callback) {
DCHECK(!SystemFonts::IsInitialized());
g_get_minimum_font_size_callback = callback;
DCHECK(!internal::SystemFonts::IsInitialized());
get_minimum_font_size_callback_ = callback;
}
// static
void PlatformFontWin::SetAdjustFontCallback(AdjustFontCallback callback) {
DCHECK(!SystemFonts::IsInitialized());
g_adjust_font_callback = callback;
DCHECK(!internal::SystemFonts::IsInitialized());
adjust_font_callback_ = callback;
}
// static
......@@ -386,7 +376,27 @@ bool PlatformFontWin::IsDirectWriteEnabled() {
// static
const Font& PlatformFontWin::GetSystemFont(SystemFont system_font) {
return SystemFonts::Instance()->GetFont(system_font);
return internal::SystemFonts::Instance()->GetFont(system_font);
}
// static
Font PlatformFontWin::AdjustExistingFont(
NativeFont existing_font,
const FontAdjustment& font_adjustment) {
LOGFONT logfont;
auto result = GetObject(existing_font, sizeof(logfont), &logfont);
DCHECK(result);
// Make the necessary adjustments.
AdjustLOGFONT(font_adjustment, &logfont);
// Cap at minimum font size.
logfont.lfHeight = AdjustFontSize(logfont.lfHeight, 0);
// Create the Font object.
HFONT hfont = CreateFontIndirect(&logfont);
DCHECK(hfont);
return HFontToFont(hfont);
}
////////////////////////////////////////////////////////////////////////////////
......@@ -507,8 +517,10 @@ PlatformFontWin::HFontRef* PlatformFontWin::GetBaseFontRef() {
if (base_font_ref_ == nullptr) {
// We'll delegate to our SystemFonts instance to give us the default
// message font.
PlatformFontWin* message_font = static_cast<PlatformFontWin*>(
SystemFonts::Instance()->GetFont(SystemFont::kMessage).platform_font());
PlatformFontWin* message_font =
static_cast<PlatformFontWin*>(internal::SystemFonts::Instance()
->GetFont(SystemFont::kMessage)
.platform_font());
base_font_ref_ = message_font->font_ref_.get();
}
return base_font_ref_;
......@@ -649,6 +661,50 @@ PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia(
ToGfxFontWeight(font_info.lfWeight), style);
}
// static
int PlatformFontWin::AdjustFontSize(int lf_height, int size_delta) {
// Extract out the sign of |lf_height| - we'll add it back later.
const int lf_sign = lf_height < 0 ? -1 : 1;
lf_height = std::abs(lf_height);
// Apply the size adjustment.
lf_height += size_delta;
// Make sure |lf_height| is not smaller than allowed min allowed font size.
int min_font_size = 0;
if (get_minimum_font_size_callback_) {
min_font_size = get_minimum_font_size_callback_();
DCHECK_GE(min_font_size, 0);
}
lf_height = std::max(min_font_size, lf_height);
// Add back the sign.
return lf_sign * lf_height;
}
// static
void PlatformFontWin::AdjustLOGFONT(
const gfx::PlatformFontWin::FontAdjustment& font_adjustment,
LOGFONT* logfont) {
DCHECK_GT(font_adjustment.font_scale, 0.0);
LONG new_height =
LONG{std::round(logfont->lfHeight * font_adjustment.font_scale)};
if (logfont->lfHeight && !new_height)
new_height = logfont->lfHeight > 0 ? 1 : -1;
logfont->lfHeight = new_height;
if (!font_adjustment.font_family_override.empty()) {
auto result = wcscpy_s(logfont->lfFaceName,
font_adjustment.font_family_override.c_str());
DCHECK_EQ(0, result) << "Font name " << font_adjustment.font_family_override
<< " cannot be copied into LOGFONT structure.";
}
}
// static
Font PlatformFontWin::HFontToFont(HFONT hfont) {
return Font(new PlatformFontWin(CreateHFontRef(hfont)));
}
PlatformFontWin::PlatformFontWin(HFontRef* hfont_ref) : font_ref_(hfont_ref) {
}
......
......@@ -21,6 +21,10 @@ struct IDWriteFont;
namespace gfx {
namespace internal {
class SystemFonts;
}
class GFX_EXPORT PlatformFontWin : public PlatformFont {
public:
enum class SystemFont : int {
......@@ -31,6 +35,12 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
kMessage
};
// Represents an optional override of system font and scale.
struct FontAdjustment {
base::string16 font_family_override;
double font_scale = 1.0;
};
PlatformFontWin();
explicit PlatformFontWin(NativeFont native_font);
PlatformFontWin(const std::string& font_name, int font_size);
......@@ -50,11 +60,11 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
static void SetGetMinimumFontSizeCallback(
GetMinimumFontSizeCallback callback);
// Callback that adjusts a LOGFONT to meet suitability requirements of the
// embedding application. Optional. If not specified, no adjustments are
// performed other than clamping to a minimum font height if
// Callback that adjusts a SystemFontInfo to meet suitability requirements
// of the embedding application. Optional. If not specified, no adjustments
// are performed other than clamping to a minimum font size if
// |get_minimum_font_size_callback| is specified.
typedef void (*AdjustFontCallback)(LOGFONT* lf);
typedef void (*AdjustFontCallback)(FontAdjustment* font_adjustment);
static void SetAdjustFontCallback(AdjustFontCallback callback);
// Returns the font name for the system locale. Some fonts, particularly
......@@ -84,12 +94,31 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
static bool IsDirectWriteEnabled();
// Returns the specified Windows system font, suitable for drawing on screen
// elements.
static const Font& GetSystemFont(SystemFont system_font);
// Apply a font adjustment to an existing font.
static Font AdjustExistingFont(NativeFont existing_font,
const FontAdjustment& font_adjustment);
private:
friend class internal::SystemFonts;
FRIEND_TEST_ALL_PREFIXES(RenderTextHarfBuzzTest, HarfBuzz_UniscribeFallback);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, Metrics_SkiaVersusGDI);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, DirectWriteFontSubstitution);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, AdjustFontSize);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest,
AdjustFontSize_MinimumSizeSpecified);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, AdjustLOGFONT_NoAdjustment);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, AdjustLOGFONT_ChangeFace);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, AdjustLOGFONT_ScaleDown);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest,
AdjustLOGFONT_ScaleDownWithRounding);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest,
AdjustLOGFONT_ScaleUpWithFaceChange);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest,
AdjustLOGFONT_ScaleUpWithRounding);
~PlatformFontWin() override;
......@@ -202,6 +231,22 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
HFONT gdi_font,
const TEXTMETRIC& font_metrics);
// Adjust a font smaller or larger, subject to the global minimum size.
// |lf_height| is the height as reported by the LOGFONT structure, and may
// be positive or negative (but is typically negative, indicating character
// size rather than cell size). The absolute value of |lf_size| will be
// adjusted by |size_delta| and then returned with the original sign.
static int AdjustFontSize(int lf_height, int size_delta);
// Adjust a LOGFONT structure for optional size scale and face override.
static void AdjustLOGFONT(const FontAdjustment& font_adjustment,
LOGFONT* logfont);
// Takes control of a native font (e.g. from CreateFontIndirect()) and wraps
// it in a Font object to manage its lifespan. Note that |hfont| may not be
// valid after the call; use the returned Font object instead.
static Font HFontToFont(HFONT hfont);
// Creates a new PlatformFontWin with the specified HFontRef. Used when
// constructing a Font from a HFONT we don't want to copy.
explicit PlatformFontWin(HFontRef* hfont_ref);
......@@ -215,6 +260,12 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
// Pointer to the global IDWriteFactory interface.
static IDWriteFactory* direct_write_factory_;
// Font adjustment callback.
static AdjustFontCallback adjust_font_callback_;
// Minimum size callback.
static GetMinimumFontSizeCallback get_minimum_font_size_callback_;
DISALLOW_COPY_AND_ASSIGN(PlatformFontWin);
};
......
......@@ -4,6 +4,10 @@
#include "ui/gfx/platform_font_win.h"
#include <memory.h>
#include <string.h>
#include <windows.h>
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
......@@ -17,6 +21,121 @@
namespace gfx {
TEST(PlatformFontWinTest, AdjustFontSize) {
PlatformFontWin::SetGetMinimumFontSizeCallback(nullptr);
EXPECT_EQ(10, PlatformFontWin::AdjustFontSize(10, 0));
EXPECT_EQ(-10, PlatformFontWin::AdjustFontSize(-10, 0));
EXPECT_EQ(8, PlatformFontWin::AdjustFontSize(10, -2));
EXPECT_EQ(-8, PlatformFontWin::AdjustFontSize(-10, -2));
EXPECT_EQ(13, PlatformFontWin::AdjustFontSize(10, 3));
EXPECT_EQ(-13, PlatformFontWin::AdjustFontSize(-10, 3));
EXPECT_EQ(1, PlatformFontWin::AdjustFontSize(10, -9));
EXPECT_EQ(-1, PlatformFontWin::AdjustFontSize(-10, -9));
EXPECT_EQ(0, PlatformFontWin::AdjustFontSize(10, -12));
EXPECT_EQ(0, PlatformFontWin::AdjustFontSize(-10, -12));
}
TEST(PlatformFontWinTest, AdjustFontSize_MinimumSizeSpecified) {
PlatformFontWin::SetGetMinimumFontSizeCallback([] { return 1; });
EXPECT_EQ(10, PlatformFontWin::AdjustFontSize(10, 0));
EXPECT_EQ(-10, PlatformFontWin::AdjustFontSize(-10, 0));
EXPECT_EQ(8, PlatformFontWin::AdjustFontSize(10, -2));
EXPECT_EQ(-8, PlatformFontWin::AdjustFontSize(-10, -2));
EXPECT_EQ(13, PlatformFontWin::AdjustFontSize(10, 3));
EXPECT_EQ(-13, PlatformFontWin::AdjustFontSize(-10, 3));
EXPECT_EQ(1, PlatformFontWin::AdjustFontSize(10, -9));
EXPECT_EQ(-1, PlatformFontWin::AdjustFontSize(-10, -9));
EXPECT_EQ(1, PlatformFontWin::AdjustFontSize(10, -12));
EXPECT_EQ(-1, PlatformFontWin::AdjustFontSize(-10, -12));
}
namespace {
LOGFONT CreateLOGFONT(const base::string16& name, LONG height) {
LOGFONT logfont{};
logfont.lfHeight = height;
auto result = wcscpy_s(logfont.lfFaceName, name.c_str());
DCHECK_EQ(0, result);
return logfont;
}
const base::string16 kSegoeUI(L"Segoe UI");
const base::string16 kArial(L"Arial");
} // namespace
TEST(PlatformFontWinTest, AdjustLOGFONT_NoAdjustment) {
LOGFONT logfont = CreateLOGFONT(kSegoeUI, -12);
PlatformFontWin::FontAdjustment adjustment;
PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
EXPECT_EQ(-12, logfont.lfHeight);
EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
}
TEST(PlatformFontWinTest, AdjustLOGFONT_ChangeFace) {
LOGFONT logfont = CreateLOGFONT(kSegoeUI, -12);
PlatformFontWin::FontAdjustment adjustment{kArial, 1.0};
PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
EXPECT_EQ(-12, logfont.lfHeight);
EXPECT_EQ(kArial, logfont.lfFaceName);
}
TEST(PlatformFontWinTest, AdjustLOGFONT_ScaleDown) {
LOGFONT logfont = CreateLOGFONT(kSegoeUI, -12);
PlatformFontWin::FontAdjustment adjustment{L"", 0.5};
PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
EXPECT_EQ(-6, logfont.lfHeight);
EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
logfont = CreateLOGFONT(kSegoeUI, 12);
adjustment = {L"", 0.5};
PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
EXPECT_EQ(6, logfont.lfHeight);
EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
}
TEST(PlatformFontWinTest, AdjustLOGFONT_ScaleDownWithRounding) {
LOGFONT logfont = CreateLOGFONT(kSegoeUI, -10);
PlatformFontWin::FontAdjustment adjustment{L"", 0.85};
PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
EXPECT_EQ(-9, logfont.lfHeight);
EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
logfont = CreateLOGFONT(kSegoeUI, 10);
adjustment = {L"", 0.85};
PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
EXPECT_EQ(9, logfont.lfHeight);
EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
}
TEST(PlatformFontWinTest, AdjustLOGFONT_ScaleUpWithFaceChange) {
LOGFONT logfont = CreateLOGFONT(kSegoeUI, -12);
PlatformFontWin::FontAdjustment adjustment{kArial, 1.5};
PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
EXPECT_EQ(-18, logfont.lfHeight);
EXPECT_EQ(kArial, logfont.lfFaceName);
logfont = CreateLOGFONT(kSegoeUI, 12);
adjustment = {kArial, 1.5};
PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
EXPECT_EQ(18, logfont.lfHeight);
EXPECT_EQ(kArial, logfont.lfFaceName);
}
TEST(PlatformFontWinTest, AdjustLOGFONT_ScaleUpWithRounding) {
LOGFONT logfont = CreateLOGFONT(kSegoeUI, -10);
PlatformFontWin::FontAdjustment adjustment{L"", 1.111};
PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
EXPECT_EQ(-11, logfont.lfHeight);
EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
logfont = CreateLOGFONT(kSegoeUI, 10);
adjustment = {L"", 1.11};
PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
EXPECT_EQ(11, logfont.lfHeight);
EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
}
// Test whether font metrics retrieved by DirectWrite (skia) and GDI match as
// per assumptions mentioned below:-
// 1. Font size is the same
......
......@@ -4,6 +4,7 @@
#include "ui/views/corewm/tooltip_win.h"
#include <windowsx.h>
#include <winuser.h>
#include "base/debug/stack_trace.h"
......@@ -14,6 +15,7 @@
#include "ui/display/screen.h"
#include "ui/display/win/screen_win.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/platform_font_win.h"
#include "ui/views/corewm/cursor_height_provider_win.h"
namespace views {
......@@ -70,7 +72,7 @@ bool TooltipWin::EnsureTooltipWindow() {
return false;
}
l10n_util::AdjustUIFontForWindow(tooltip_hwnd_);
MaybeOverrideFont();
SendMessage(tooltip_hwnd_, TTM_ADDTOOL, 0,
reinterpret_cast<LPARAM>(&toolinfo_));
......@@ -96,6 +98,33 @@ void TooltipWin::PositionTooltip() {
display.work_area()));
SetWindowPos(tooltip_hwnd_, NULL, tooltip_bounds.x(), tooltip_bounds.y(), 0,
0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
MaybeOverrideFont();
}
void TooltipWin::MaybeOverrideFont() {
gfx::PlatformFontWin::FontAdjustment font_adjustment;
const HFONT old_font = GetWindowFont(tooltip_hwnd_);
// Determine if we need to override the font.
if ((!override_font_ || override_font_->GetNativeFont() != old_font) &&
l10n_util::NeedOverrideDefaultUIFont(
&font_adjustment.font_family_override, &font_adjustment.font_scale)) {
// Determine if we need to regenerate the font.
// There are a number of situations under which Windows can replace the
// font in a tooltip, but we don't actually need to regenerate our override
// font unless the underlying text/DPI scale of the window has changed.
const float current_scale =
display::win::ScreenWin::GetScaleFactorForHWND(tooltip_hwnd_);
if (!override_font_ || current_scale != override_scale_) {
override_font_ =
gfx::PlatformFontWin::AdjustExistingFont(old_font, font_adjustment);
override_scale_ = current_scale;
}
// Override the font in the tooltip.
SetWindowFont(tooltip_hwnd_, override_font_->GetNativeFont(), FALSE);
}
}
int TooltipWin::GetMaxWidth(const gfx::Point& location) const {
......@@ -116,12 +145,6 @@ void TooltipWin::SetText(aura::Window* window,
// See comment in header for details on why |location_| is needed.
location_ = location;
// Without this we get a flicker of the tooltip appearing at 0x0. Not sure
// why.
SetWindowPos(tooltip_hwnd_, NULL, 0, 0, 0, 0,
SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE |
SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
base::string16 adjusted_text(tooltip_text);
base::i18n::AdjustStringForLocaleDirection(&adjusted_text);
toolinfo_.lpszText = const_cast<WCHAR*>(adjusted_text.c_str());
......@@ -138,8 +161,6 @@ void TooltipWin::Show() {
SendMessage(tooltip_hwnd_, TTM_TRACKACTIVATE,
TRUE, reinterpret_cast<LPARAM>(&toolinfo_));
SetWindowPos(tooltip_hwnd_, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSIZE);
}
void TooltipWin::Hide() {
......
......@@ -5,15 +5,17 @@
#ifndef UI_VIEWS_COREWM_TOOLTIP_WIN_H_
#define UI_VIEWS_COREWM_TOOLTIP_WIN_H_
#include <windows.h>
#include <commctrl.h>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/optional.h"
#include "base/strings/string16.h"
#include "ui/gfx/font.h"
#include "ui/gfx/geometry/point.h"
#include "ui/views/corewm/tooltip.h"
#include <windows.h>
#include <commctrl.h>
namespace views {
namespace corewm {
......@@ -36,6 +38,9 @@ class VIEWS_EXPORT TooltipWin : public Tooltip {
// Sets the position of the tooltip.
void PositionTooltip();
// Might override the font size for localization (e.g. Hindi).
void MaybeOverrideFont();
// Tooltip:
int GetMaxWidth(const gfx::Point& location) const override;
void SetText(aura::Window* window,
......@@ -45,6 +50,11 @@ class VIEWS_EXPORT TooltipWin : public Tooltip {
void Hide() override;
bool IsVisible() override;
// Font we're currently overriding our UI font with.
// (Lets us keep a handle around so we don't leak.)
// Should outlast |tooltip_hwnd_|.
base::Optional<gfx::Font> override_font_;
// The window |tooltip_hwnd_| is parented to.
HWND parent_hwnd_;
......@@ -62,6 +72,10 @@ class VIEWS_EXPORT TooltipWin : public Tooltip {
// cache it.
gfx::Point location_;
// What the scale was the last time we overrode the font, to see if we can
// re-use our previous override.
float override_scale_ = 0.0f;
DISALLOW_COPY_AND_ASSIGN(TooltipWin);
};
......
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