OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ui/base/l10n/l10n_util_win.h" | |
6 | |
7 #include <windowsx.h> | |
8 #include <algorithm> | |
9 #include <iterator> | |
10 | |
11 #include "base/i18n/rtl.h" | |
12 #include "base/lazy_instance.h" | |
13 #include "base/strings/string_number_conversions.h" | |
14 #include "base/strings/string_util.h" | |
15 #include "base/strings/utf_string_conversions.h" | |
16 #include "base/win/i18n.h" | |
17 #include "base/win/windows_version.h" | |
18 #include "ui/base/l10n/l10n_util.h" | |
19 #include "ui/gfx/display.h" | |
20 #include "ui/gfx/win/dpi.h" | |
21 #include "ui/strings/grit/app_locale_settings.h" | |
22 | |
23 namespace { | |
24 | |
25 void AdjustLogFont(const base::string16& font_family, | |
26 double font_size_scaler, | |
27 double dpi_scale, | |
28 LOGFONT* logfont) { | |
29 DCHECK(font_size_scaler > 0); | |
30 font_size_scaler = std::max(std::min(font_size_scaler, 2.0), 0.7); | |
31 // Font metrics are computed in pixels and scale in high-DPI mode. | |
32 // Normalized by the DPI scale factor in order to work in DIP with | |
33 // Views/Aura. Call with dpi_scale=1 to keep the size in pixels. | |
34 font_size_scaler /= dpi_scale; | |
35 logfont->lfHeight = static_cast<long>(font_size_scaler * | |
36 static_cast<double>(abs(logfont->lfHeight)) + 0.5) * | |
37 (logfont->lfHeight > 0 ? 1 : -1); | |
38 | |
39 // TODO(jungshik): We may want to check the existence of the font. | |
40 // If it's not installed, we shouldn't adjust the font. | |
41 if (font_family != L"default") { | |
42 int name_len = std::min(static_cast<int>(font_family.size()), | |
43 LF_FACESIZE -1); | |
44 memcpy(logfont->lfFaceName, font_family.data(), name_len * sizeof(WORD)); | |
45 logfont->lfFaceName[name_len] = 0; | |
46 } | |
47 } | |
48 | |
49 bool IsFontPresent(const wchar_t* font_name) { | |
50 HFONT hfont = CreateFont(12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
51 font_name); | |
52 if (hfont == NULL) | |
53 return false; | |
54 HDC dc = GetDC(0); | |
55 HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont)); | |
56 WCHAR actual_font_name[LF_FACESIZE]; | |
57 int size_ret = GetTextFace(dc, LF_FACESIZE, actual_font_name); | |
58 SelectObject(dc, oldFont); | |
59 DeleteObject(hfont); | |
60 ReleaseDC(0, dc); | |
61 // We don't have to worry about East Asian fonts with locale-dependent | |
62 // names here. | |
63 return (size_ret != 0) && wcscmp(font_name, actual_font_name) == 0; | |
64 } | |
65 | |
66 class OverrideLocaleHolder { | |
67 public: | |
68 OverrideLocaleHolder() {} | |
69 const std::vector<std::string>& value() const { return value_; } | |
70 void swap_value(std::vector<std::string>* override_value) { | |
71 value_.swap(*override_value); | |
72 } | |
73 private: | |
74 std::vector<std::string> value_; | |
75 DISALLOW_COPY_AND_ASSIGN(OverrideLocaleHolder); | |
76 }; | |
77 | |
78 base::LazyInstance<OverrideLocaleHolder> override_locale_holder = | |
79 LAZY_INSTANCE_INITIALIZER; | |
80 | |
81 } // namespace | |
82 | |
83 namespace l10n_util { | |
84 | |
85 int GetExtendedStyles() { | |
86 return !base::i18n::IsRTL() ? 0 : WS_EX_LAYOUTRTL | WS_EX_RTLREADING; | |
87 } | |
88 | |
89 int GetExtendedTooltipStyles() { | |
90 return !base::i18n::IsRTL() ? 0 : WS_EX_LAYOUTRTL; | |
91 } | |
92 | |
93 void HWNDSetRTLLayout(HWND hwnd) { | |
94 DWORD ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE); | |
95 | |
96 // We don't have to do anything if the style is already set for the HWND. | |
97 if (!(ex_style & WS_EX_LAYOUTRTL)) { | |
98 ex_style |= WS_EX_LAYOUTRTL; | |
99 ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style); | |
100 | |
101 // Right-to-left layout changes are not applied to the window immediately | |
102 // so we should make sure a WM_PAINT is sent to the window by invalidating | |
103 // the entire window rect. | |
104 ::InvalidateRect(hwnd, NULL, true); | |
105 } | |
106 } | |
107 | |
108 bool IsLocaleSupportedByOS(const std::string& locale) { | |
109 // Block Amharic on Windows XP unless 'Abyssinica SIL' font is present. | |
110 // On Win XP, no Ethiopic/Amahric font is availabel out of box. We hard-coded | |
111 // 'Abyssinica SIL' in the resource bundle to use in the UI. Check | |
112 // for its presence to determine whether or not to support Amharic UI on XP. | |
113 return (base::win::GetVersion() >= base::win::VERSION_VISTA || | |
114 !LowerCaseEqualsASCII(locale, "am") || IsFontPresent(L"Abyssinica SIL")); | |
115 } | |
116 | |
117 bool NeedOverrideDefaultUIFont(base::string16* override_font_family, | |
118 double* font_size_scaler) { | |
119 // This is rather simple-minded to deal with the UI font size | |
120 // issue for some Indian locales (ml, bn, hi) for which | |
121 // the default Windows fonts are too small to be legible. For those | |
122 // locales, IDS_UI_FONT_FAMILY is set to an actual font family to | |
123 // use while for other locales, it's set to 'default'. | |
124 | |
125 // XP and Vista or later have different font size issues and | |
126 // we need separate ui font specifications. | |
127 int ui_font_family_id = IDS_UI_FONT_FAMILY; | |
128 int ui_font_size_scaler_id = IDS_UI_FONT_SIZE_SCALER; | |
129 if (base::win::GetVersion() < base::win::VERSION_VISTA) { | |
130 ui_font_family_id = IDS_UI_FONT_FAMILY_XP; | |
131 ui_font_size_scaler_id = IDS_UI_FONT_SIZE_SCALER_XP; | |
132 } | |
133 | |
134 base::string16 ui_font_family = GetStringUTF16(ui_font_family_id); | |
135 int scaler100; | |
136 if (!base::StringToInt(l10n_util::GetStringUTF16(ui_font_size_scaler_id), | |
137 &scaler100)) | |
138 return false; | |
139 | |
140 // We use the OS default in two cases: | |
141 // 1) The resource bundle has 'default' and '100' for font family and | |
142 // font scaler. | |
143 // 2) The resource bundle is not available for some reason and | |
144 // ui_font_family is empty. | |
145 if (ui_font_family == L"default" && scaler100 == 100 || | |
146 ui_font_family.empty()) | |
147 return false; | |
148 if (override_font_family && font_size_scaler) { | |
149 override_font_family->swap(ui_font_family); | |
150 *font_size_scaler = scaler100 / 100.0; | |
151 } | |
152 return true; | |
153 } | |
154 | |
155 void AdjustUIFont(LOGFONT* logfont) { | |
156 float dpi_scale = gfx::GetDPIScale(); | |
157 if (gfx::Display::HasForceDeviceScaleFactor()) { | |
158 // If the scale is forced, we don't need to adjust it here. | |
159 dpi_scale = 1.0f; | |
160 } | |
161 AdjustUIFontForDIP(dpi_scale, logfont); | |
162 } | |
163 | |
164 void AdjustUIFontForDIP(float dpi_scale, LOGFONT* logfont) { | |
165 base::string16 ui_font_family = L"default"; | |
166 double ui_font_size_scaler = 1; | |
167 if (NeedOverrideDefaultUIFont(&ui_font_family, &ui_font_size_scaler) || | |
168 dpi_scale != 1) { | |
169 AdjustLogFont(ui_font_family, ui_font_size_scaler, dpi_scale, logfont); | |
170 } | |
171 } | |
172 | |
173 void AdjustUIFontForWindow(HWND hwnd) { | |
174 base::string16 ui_font_family; | |
175 double ui_font_size_scaler; | |
176 if (NeedOverrideDefaultUIFont(&ui_font_family, &ui_font_size_scaler)) { | |
177 LOGFONT logfont; | |
178 if (GetObject(GetWindowFont(hwnd), sizeof(logfont), &logfont)) { | |
179 double dpi_scale = 1; | |
180 AdjustLogFont(ui_font_family, ui_font_size_scaler, dpi_scale, &logfont); | |
181 HFONT hfont = CreateFontIndirect(&logfont); | |
182 if (hfont) | |
183 SetWindowFont(hwnd, hfont, FALSE); | |
184 } | |
185 } | |
186 } | |
187 | |
188 void OverrideLocaleWithUILanguageList() { | |
189 std::vector<base::string16> ui_languages; | |
190 if (base::win::i18n::GetThreadPreferredUILanguageList(&ui_languages)) { | |
191 std::vector<std::string> ascii_languages; | |
192 ascii_languages.reserve(ui_languages.size()); | |
193 std::transform(ui_languages.begin(), ui_languages.end(), | |
194 std::back_inserter(ascii_languages), &base::UTF16ToASCII); | |
195 override_locale_holder.Get().swap_value(&ascii_languages); | |
196 } else { | |
197 NOTREACHED() << "Failed to determine the UI language for locale override."; | |
198 } | |
199 } | |
200 | |
201 const std::vector<std::string>& GetLocaleOverrides() { | |
202 return override_locale_holder.Get().value(); | |
203 } | |
204 | |
205 } // namespace l10n_util | |
OLD | NEW |