1 // Copyright 2014 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 "ui/gfx/font_list_impl.h"
9 #include "base/logging.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "ui/gfx/font.h"
13 #include "ui/gfx/font_list.h"
17 // Returns a font description from |families|, |style|, and |size_pixels|.
18 std::string
BuildDescription(const std::vector
<std::string
>& families
,
21 std::string description
= base::JoinString(families
, ",");
24 if (style
& gfx::Font::BOLD
)
25 description
+= "Bold ";
26 if (style
& gfx::Font::ITALIC
)
27 description
+= "Italic ";
29 description
+= base::IntToString(size_pixels
);
39 FontListImpl::FontListImpl(const std::string
& font_description_string
)
40 : font_description_string_(font_description_string
),
45 DCHECK(!font_description_string
.empty());
46 // DCHECK description string ends with "px" for size in pixel.
47 DCHECK(base::EndsWith(font_description_string
, "px",
48 base::CompareCase::SENSITIVE
));
51 FontListImpl::FontListImpl(const std::vector
<std::string
>& font_names
,
54 : font_description_string_(BuildDescription(font_names
, font_style
,
58 font_style_(font_style
),
59 font_size_(font_size
) {
60 DCHECK(!font_names
.empty());
61 DCHECK(!font_names
[0].empty());
64 FontListImpl::FontListImpl(const std::vector
<Font
>& fonts
)
70 DCHECK(!fonts
.empty());
71 font_style_
= fonts
[0].GetStyle();
72 font_size_
= fonts
[0].GetFontSize();
74 for (size_t i
= 1; i
< fonts
.size(); ++i
) {
75 DCHECK_EQ(fonts
[i
].GetStyle(), font_style_
);
76 DCHECK_EQ(fonts
[i
].GetFontSize(), font_size_
);
81 FontListImpl::FontListImpl(const Font
& font
)
86 fonts_
.push_back(font
);
89 FontListImpl
* FontListImpl::Derive(int size_delta
, int font_style
) const {
90 // If there is a font vector, derive from that.
91 if (!fonts_
.empty()) {
92 std::vector
<Font
> fonts
= fonts_
;
93 for (size_t i
= 0; i
< fonts
.size(); ++i
)
94 fonts
[i
] = fonts
[i
].Derive(size_delta
, font_style
);
95 return new FontListImpl(fonts
);
98 // Otherwise, parse the font description string to derive from it.
99 std::vector
<std::string
> font_names
;
102 CHECK(FontList::ParseDescription(font_description_string_
, &font_names
,
103 &old_style
, &old_size
));
104 const int size
= std::max(1, old_size
+ size_delta
);
105 return new FontListImpl(font_names
, font_style
, size
);
108 int FontListImpl::GetHeight() const {
109 if (common_height_
== -1)
110 CacheCommonFontHeightAndBaseline();
111 return common_height_
;
114 int FontListImpl::GetBaseline() const {
115 if (common_baseline_
== -1)
116 CacheCommonFontHeightAndBaseline();
117 return common_baseline_
;
120 int FontListImpl::GetCapHeight() const {
121 // Assume the primary font is used to render Latin characters.
122 return GetPrimaryFont().GetCapHeight();
125 int FontListImpl::GetExpectedTextWidth(int length
) const {
126 // Rely on the primary font metrics for the time being.
127 return GetPrimaryFont().GetExpectedTextWidth(length
);
130 int FontListImpl::GetFontStyle() const {
131 if (font_style_
== -1)
132 CacheFontStyleAndSize();
136 int FontListImpl::GetFontSize() const {
137 if (font_size_
== -1)
138 CacheFontStyleAndSize();
142 const std::vector
<Font
>& FontListImpl::GetFonts() const {
143 if (fonts_
.empty()) {
144 DCHECK(!font_description_string_
.empty());
146 std::vector
<std::string
> font_names
;
147 // It's possible that gfx::Font::UNDERLINE is specified and it's already
148 // stored in |font_style_| but |font_description_string_| doesn't have the
149 // underline info. So we should respect |font_style_| as long as it's
152 CHECK(FontList::ParseDescription(font_description_string_
, &font_names
,
153 &style
, &font_size_
));
154 if (font_style_
== -1)
156 for (size_t i
= 0; i
< font_names
.size(); ++i
) {
157 DCHECK(!font_names
[i
].empty());
159 Font
font(font_names
[i
], font_size_
);
160 if (font_style_
== Font::NORMAL
)
161 fonts_
.push_back(font
);
163 fonts_
.push_back(font
.Derive(0, font_style_
));
169 const Font
& FontListImpl::GetPrimaryFont() const {
170 return GetFonts()[0];
173 FontListImpl::~FontListImpl() {}
175 void FontListImpl::CacheCommonFontHeightAndBaseline() const {
178 const std::vector
<Font
>& fonts
= GetFonts();
179 for (std::vector
<Font
>::const_iterator i
= fonts
.begin();
180 i
!= fonts
.end(); ++i
) {
181 ascent
= std::max(ascent
, i
->GetBaseline());
182 descent
= std::max(descent
, i
->GetHeight() - i
->GetBaseline());
184 common_height_
= ascent
+ descent
;
185 common_baseline_
= ascent
;
188 void FontListImpl::CacheFontStyleAndSize() const {
189 if (!fonts_
.empty()) {
190 font_style_
= fonts_
[0].GetStyle();
191 font_size_
= fonts_
[0].GetFontSize();
193 std::vector
<std::string
> font_names
;
194 CHECK(FontList::ParseDescription(font_description_string_
, &font_names
,
195 &font_style_
, &font_size_
));