1 // Copyright (c) 2006-2008 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.
5 #include "app/gfx/font.h"
12 #include "app/l10n_util.h"
13 #include "app/l10n_util_win.h"
14 #include "base/logging.h"
15 #include "base/string_util.h"
16 #include "base/win_util.h"
17 #include "grit/app_locale_settings.h"
22 Font::HFontRef
* Font::base_font_ref_
;
24 // If the tmWeight field of a TEXTMETRIC structure has a value >= this, the
26 static const int kTextMetricWeightBold
= 700;
28 // Returns either minimum font allowed for a current locale or
29 // lf_height + size_delta value.
30 static int AdjustFontSize(int lf_height
, int size_delta
) {
32 lf_height
-= size_delta
;
34 lf_height
+= size_delta
;
37 StringToInt(l10n_util::GetString(IDS_MINIMUM_UI_FONT_SIZE
).c_str());
38 // Make sure lf_height is not smaller than allowed min font size for current
40 if (abs(lf_height
) < min_font_size
) {
41 return lf_height
< 0 ? -min_font_size
: min_font_size
;
52 : font_ref_(GetBaseFontRef()) {
55 int Font::height() const {
56 return font_ref_
->height();
59 int Font::baseline() const {
60 return font_ref_
->baseline();
63 int Font::ave_char_width() const {
64 return font_ref_
->ave_char_width();
67 int Font::GetExpectedTextWidth(int length
) const {
68 return length
* std::min(font_ref_
->dlu_base_x(), ave_char_width());
71 int Font::style() const {
72 return font_ref_
->style();
75 NativeFont
Font::nativeFont() const {
80 Font
Font::CreateFont(HFONT font
) {
83 GetObject(font
, sizeof(LOGFONT
), &font_info
);
84 return Font(CreateHFontRef(CreateFontIndirect(&font_info
)));
87 Font
Font::CreateFont(const std::wstring
& font_name
, int font_size
) {
88 HDC hdc
= GetDC(NULL
);
89 long lf_height
= -MulDiv(font_size
, GetDeviceCaps(hdc
, LOGPIXELSY
), 72);
91 HFONT hf
= ::CreateFont(lf_height
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
93 return Font::CreateFont(hf
);
97 Font::HFontRef
* Font::GetBaseFontRef() {
98 if (base_font_ref_
== NULL
) {
99 NONCLIENTMETRICS metrics
;
100 win_util::GetNonClientMetrics(&metrics
);
102 l10n_util::AdjustUIFont(&metrics
.lfMessageFont
);
103 metrics
.lfMessageFont
.lfHeight
=
104 AdjustFontSize(metrics
.lfMessageFont
.lfHeight
, 0);
105 HFONT font
= CreateFontIndirect(&metrics
.lfMessageFont
);
107 base_font_ref_
= Font::CreateHFontRef(font
);
108 // base_font_ref_ is global, up the ref count so it's never deleted.
109 base_font_ref_
->AddRef();
111 return base_font_ref_
;
114 const std::wstring
& Font::FontName() const {
115 return font_ref_
->font_name();
118 int Font::FontSize() {
120 GetObject(hfont(), sizeof(LOGFONT
), &font_info
);
121 long lf_height
= font_info
.lfHeight
;
122 HDC hdc
= GetDC(NULL
);
123 int device_caps
= GetDeviceCaps(hdc
, LOGPIXELSY
);
125 if (device_caps
!= 0) {
126 float font_size_float
= -static_cast<float>(lf_height
)*72/device_caps
;
127 font_size
= static_cast<int>(::ceil(font_size_float
- 0.5));
129 ReleaseDC(NULL
, hdc
);
133 Font::HFontRef::HFontRef(HFONT hfont
,
142 ave_char_width_(ave_char_width
),
144 dlu_base_x_(dlu_base_x
) {
148 GetObject(hfont_
, sizeof(LOGFONT
), &font_info
);
149 font_name_
= std::wstring(font_info
.lfFaceName
);
152 Font::HFontRef::~HFontRef() {
153 DeleteObject(hfont_
);
156 Font
Font::DeriveFont(int size_delta
, int style
) const {
158 GetObject(hfont(), sizeof(LOGFONT
), &font_info
);
159 font_info
.lfHeight
= AdjustFontSize(font_info
.lfHeight
, size_delta
);
160 font_info
.lfUnderline
= ((style
& UNDERLINED
) == UNDERLINED
);
161 font_info
.lfItalic
= ((style
& ITALIC
) == ITALIC
);
162 font_info
.lfWeight
= (style
& BOLD
) ? FW_BOLD
: FW_NORMAL
;
164 HFONT hfont
= CreateFontIndirect(&font_info
);
165 return Font(CreateHFontRef(hfont
));
168 int Font::GetStringWidth(const std::wstring
& text
) const {
170 HDC dc
= GetDC(NULL
);
171 HFONT previous_font
= static_cast<HFONT
>(SelectObject(dc
, hfont()));
173 if (GetTextExtentPoint32(dc
, text
.c_str(), static_cast<int>(text
.size()),
179 SelectObject(dc
, previous_font
);
184 Font::HFontRef
* Font::CreateHFontRef(HFONT font
) {
185 TEXTMETRIC font_metrics
;
186 HDC screen_dc
= GetDC(NULL
);
187 HFONT previous_font
= static_cast<HFONT
>(SelectObject(screen_dc
, font
));
188 int last_map_mode
= SetMapMode(screen_dc
, MM_TEXT
);
189 GetTextMetrics(screen_dc
, &font_metrics
);
190 // Yes, this is how Microsoft recommends calculating the dialog unit
193 GetTextExtentPoint32(screen_dc
,
194 L
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
196 const int dlu_base_x
= (ave_text_size
.cx
/ 26 + 1) / 2;
197 // To avoid the DC referencing font_handle_, select the previous font.
198 SelectObject(screen_dc
, previous_font
);
199 SetMapMode(screen_dc
, last_map_mode
);
200 ReleaseDC(NULL
, screen_dc
);
202 const int height
= std::max(1, static_cast<int>(font_metrics
.tmHeight
));
203 const int baseline
= std::max(1, static_cast<int>(font_metrics
.tmAscent
));
204 const int ave_char_width
=
205 std::max(1, static_cast<int>(font_metrics
.tmAveCharWidth
));
207 if (font_metrics
.tmItalic
) {
208 style
|= Font::ITALIC
;
210 if (font_metrics
.tmUnderlined
) {
211 style
|= Font::UNDERLINED
;
213 if (font_metrics
.tmWeight
>= kTextMetricWeightBold
) {
217 return new HFontRef(font
, height
, baseline
, ave_char_width
, style
,