1 // Copyright (c) 2012 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.h"
7 #include "base/lazy_instance.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_split.h"
10 #include "base/strings/string_util.h"
11 #include "ui/gfx/font_list_impl.h"
15 // Font description of the default font set.
16 base::LazyInstance
<std::string
>::Leaky g_default_font_description
=
17 LAZY_INSTANCE_INITIALIZER
;
19 // The default instance of gfx::FontListImpl.
20 base::LazyInstance
<scoped_refptr
<gfx::FontListImpl
> >::Leaky g_default_impl
=
21 LAZY_INSTANCE_INITIALIZER
;
22 bool g_default_impl_initialized
= false;
29 bool FontList::ParseDescription(const std::string
& description
,
30 std::vector
<std::string
>* families_out
,
32 int* size_pixels_out
) {
35 DCHECK(size_pixels_out
);
37 base::SplitString(description
, ',', families_out
);
38 if (families_out
->empty())
40 for (auto& family
: *families_out
)
41 base::TrimWhitespaceASCII(family
, base::TRIM_ALL
, &family
);
43 // The last item is "[STYLE1] [STYLE2] [...] SIZE".
44 std::vector
<std::string
> styles
;
45 base::SplitStringAlongWhitespace(families_out
->back(), &styles
);
46 families_out
->pop_back();
50 // The size takes the form "<INT>px".
51 std::string size_string
= styles
.back();
53 if (!EndsWith(size_string
, "px", true /* case_sensitive */))
55 size_string
.resize(size_string
.size() - 2);
56 if (!base::StringToInt(size_string
, size_pixels_out
) ||
57 *size_pixels_out
<= 0)
60 // Font supports BOLD and ITALIC; underline is supported via RenderText.
61 *style_out
= gfx::Font::NORMAL
;
62 for (const auto& style_string
: styles
) {
63 if (style_string
== "Bold")
64 *style_out
|= gfx::Font::BOLD
;
65 else if (style_string
== "Italic")
66 *style_out
|= gfx::Font::ITALIC
;
74 FontList::FontList() : impl_(GetDefaultImpl()) {}
76 FontList::FontList(const FontList
& other
) : impl_(other
.impl_
) {}
78 FontList::FontList(const std::string
& font_description_string
)
79 : impl_(new FontListImpl(font_description_string
)) {}
81 FontList::FontList(const std::vector
<std::string
>& font_names
,
84 : impl_(new FontListImpl(font_names
, font_style
, font_size
)) {}
86 FontList::FontList(const std::vector
<Font
>& fonts
)
87 : impl_(new FontListImpl(fonts
)) {}
89 FontList::FontList(const Font
& font
) : impl_(new FontListImpl(font
)) {}
91 FontList::~FontList() {}
93 FontList
& FontList::operator=(const FontList
& other
) {
99 void FontList::SetDefaultFontDescription(const std::string
& font_description
) {
100 // The description string must end with "px" for size in pixel, or must be
101 // the empty string, which specifies to use a single default font.
102 DCHECK(font_description
.empty() ||
103 EndsWith(font_description
, "px", true));
105 g_default_font_description
.Get() = font_description
;
106 g_default_impl_initialized
= false;
109 FontList
FontList::Derive(int size_delta
, int font_style
) const {
110 return FontList(impl_
->Derive(size_delta
, font_style
));
113 FontList
FontList::DeriveWithSizeDelta(int size_delta
) const {
114 return Derive(size_delta
, GetFontStyle());
117 FontList
FontList::DeriveWithStyle(int font_style
) const {
118 return Derive(0, font_style
);
121 gfx::FontList
FontList::DeriveWithHeightUpperBound(int height
) const {
122 gfx::FontList
font_list(*this);
123 for (int font_size
= font_list
.GetFontSize(); font_size
> 1; --font_size
) {
124 const int internal_leading
=
125 font_list
.GetBaseline() - font_list
.GetCapHeight();
126 // Some platforms don't support getting the cap height, and simply return
127 // the entire font ascent from GetCapHeight(). Centering the ascent makes
128 // the font look too low, so if GetCapHeight() returns the ascent, center
129 // the entire font height instead.
131 height
- ((internal_leading
!= 0) ?
132 font_list
.GetCapHeight() : font_list
.GetHeight());
133 const int y_offset
= space
/ 2 - internal_leading
;
134 const int space_at_bottom
= height
- (y_offset
+ font_list
.GetHeight());
135 if ((y_offset
>= 0) && (space_at_bottom
>= 0))
137 font_list
= font_list
.DeriveWithSizeDelta(-1);
142 int FontList::GetHeight() const {
143 return impl_
->GetHeight();
146 int FontList::GetBaseline() const {
147 return impl_
->GetBaseline();
150 int FontList::GetCapHeight() const {
151 return impl_
->GetCapHeight();
154 int FontList::GetExpectedTextWidth(int length
) const {
155 return impl_
->GetExpectedTextWidth(length
);
158 int FontList::GetFontStyle() const {
159 return impl_
->GetFontStyle();
162 int FontList::GetFontSize() const {
163 return impl_
->GetFontSize();
166 const std::vector
<Font
>& FontList::GetFonts() const {
167 return impl_
->GetFonts();
170 const Font
& FontList::GetPrimaryFont() const {
171 return impl_
->GetPrimaryFont();
174 FontList::FontList(FontListImpl
* impl
) : impl_(impl
) {}
177 const scoped_refptr
<FontListImpl
>& FontList::GetDefaultImpl() {
178 // SetDefaultFontDescription() must be called and the default font description
179 // must be set earlier than any call of this function.
180 DCHECK(!(g_default_font_description
== NULL
)) // != is not overloaded.
181 << "SetDefaultFontDescription has not been called.";
183 if (!g_default_impl_initialized
) {
184 g_default_impl
.Get() =
185 g_default_font_description
.Get().empty() ?
186 new FontListImpl(Font()) :
187 new FontListImpl(g_default_font_description
.Get());
188 g_default_impl_initialized
= true;
191 return g_default_impl
.Get();