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 *families_out
= base::SplitString(
38 description
, ",", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
39 if (families_out
->empty())
41 for (auto& family
: *families_out
)
42 base::TrimWhitespaceASCII(family
, base::TRIM_ALL
, &family
);
44 // The last item is "[STYLE1] [STYLE2] [...] SIZE".
45 std::vector
<std::string
> styles
= base::SplitString(
46 families_out
->back(), base::kWhitespaceASCII
,
47 base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
48 families_out
->pop_back();
52 // The size takes the form "<INT>px".
53 std::string size_string
= styles
.back();
55 if (!base::EndsWith(size_string
, "px", base::CompareCase::SENSITIVE
))
57 size_string
.resize(size_string
.size() - 2);
58 if (!base::StringToInt(size_string
, size_pixels_out
) ||
59 *size_pixels_out
<= 0)
62 // Font supports BOLD and ITALIC; underline is supported via RenderText.
63 *style_out
= gfx::Font::NORMAL
;
64 for (const auto& style_string
: styles
) {
65 if (style_string
== "Bold")
66 *style_out
|= gfx::Font::BOLD
;
67 else if (style_string
== "Italic")
68 *style_out
|= gfx::Font::ITALIC
;
76 FontList::FontList() : impl_(GetDefaultImpl()) {}
78 FontList::FontList(const FontList
& other
) : impl_(other
.impl_
) {}
80 FontList::FontList(const std::string
& font_description_string
)
81 : impl_(new FontListImpl(font_description_string
)) {}
83 FontList::FontList(const std::vector
<std::string
>& font_names
,
86 : impl_(new FontListImpl(font_names
, font_style
, font_size
)) {}
88 FontList::FontList(const std::vector
<Font
>& fonts
)
89 : impl_(new FontListImpl(fonts
)) {}
91 FontList::FontList(const Font
& font
) : impl_(new FontListImpl(font
)) {}
93 FontList::~FontList() {}
95 FontList
& FontList::operator=(const FontList
& other
) {
101 void FontList::SetDefaultFontDescription(const std::string
& font_description
) {
102 // The description string must end with "px" for size in pixel, or must be
103 // the empty string, which specifies to use a single default font.
104 DCHECK(font_description
.empty() ||
105 base::EndsWith(font_description
, "px", base::CompareCase::SENSITIVE
));
107 g_default_font_description
.Get() = font_description
;
108 g_default_impl_initialized
= false;
111 FontList
FontList::Derive(int size_delta
, int font_style
) const {
112 return FontList(impl_
->Derive(size_delta
, font_style
));
115 FontList
FontList::DeriveWithSizeDelta(int size_delta
) const {
116 return Derive(size_delta
, GetFontStyle());
119 FontList
FontList::DeriveWithStyle(int font_style
) const {
120 return Derive(0, font_style
);
123 gfx::FontList
FontList::DeriveWithHeightUpperBound(int height
) const {
124 gfx::FontList
font_list(*this);
125 for (int font_size
= font_list
.GetFontSize(); font_size
> 1; --font_size
) {
126 const int internal_leading
=
127 font_list
.GetBaseline() - font_list
.GetCapHeight();
128 // Some platforms don't support getting the cap height, and simply return
129 // the entire font ascent from GetCapHeight(). Centering the ascent makes
130 // the font look too low, so if GetCapHeight() returns the ascent, center
131 // the entire font height instead.
133 height
- ((internal_leading
!= 0) ?
134 font_list
.GetCapHeight() : font_list
.GetHeight());
135 const int y_offset
= space
/ 2 - internal_leading
;
136 const int space_at_bottom
= height
- (y_offset
+ font_list
.GetHeight());
137 if ((y_offset
>= 0) && (space_at_bottom
>= 0))
139 font_list
= font_list
.DeriveWithSizeDelta(-1);
144 int FontList::GetHeight() const {
145 return impl_
->GetHeight();
148 int FontList::GetBaseline() const {
149 return impl_
->GetBaseline();
152 int FontList::GetCapHeight() const {
153 return impl_
->GetCapHeight();
156 int FontList::GetExpectedTextWidth(int length
) const {
157 return impl_
->GetExpectedTextWidth(length
);
160 int FontList::GetFontStyle() const {
161 return impl_
->GetFontStyle();
164 int FontList::GetFontSize() const {
165 return impl_
->GetFontSize();
168 const std::vector
<Font
>& FontList::GetFonts() const {
169 return impl_
->GetFonts();
172 const Font
& FontList::GetPrimaryFont() const {
173 return impl_
->GetPrimaryFont();
176 FontList::FontList(FontListImpl
* impl
) : impl_(impl
) {}
179 const scoped_refptr
<FontListImpl
>& FontList::GetDefaultImpl() {
180 // SetDefaultFontDescription() must be called and the default font description
181 // must be set earlier than any call of this function.
182 DCHECK(!(g_default_font_description
== NULL
)) // != is not overloaded.
183 << "SetDefaultFontDescription has not been called.";
185 if (!g_default_impl_initialized
) {
186 g_default_impl
.Get() =
187 g_default_font_description
.Get().empty() ?
188 new FontListImpl(Font()) :
189 new FontListImpl(g_default_font_description
.Get());
190 g_default_impl_initialized
= true;
193 return g_default_impl
.Get();