OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "ui/gfx/font_list_impl.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/strings/string_number_conversions.h" | |
11 #include "base/strings/string_split.h" | |
12 #include "base/strings/string_util.h" | |
13 #include "ui/gfx/font.h" | |
14 | |
15 namespace { | |
16 | |
17 // Parses font description into |font_names|, |font_style| and |font_size|. | |
18 void ParseFontDescriptionString(const std::string& font_description_string, | |
19 std::vector<std::string>* font_names, | |
20 int* font_style, | |
21 int* font_size) { | |
22 base::SplitString(font_description_string, ',', font_names); | |
23 DCHECK_GT(font_names->size(), 1U); | |
24 | |
25 // The last item is [STYLE_OPTIONS] SIZE. | |
26 std::vector<std::string> styles_size; | |
27 base::SplitString(font_names->back(), ' ', &styles_size); | |
28 DCHECK(!styles_size.empty()); | |
29 base::StringToInt(styles_size.back(), font_size); | |
30 DCHECK_GT(*font_size, 0); | |
31 font_names->pop_back(); | |
32 | |
33 // Font supports BOLD and ITALIC; underline is supported via RenderText. | |
34 *font_style = 0; | |
35 for (size_t i = 0; i < styles_size.size() - 1; ++i) { | |
36 // Styles are separated by white spaces. base::SplitString splits styles | |
37 // by space, and it inserts empty string for continuous spaces. | |
38 if (styles_size[i].empty()) | |
39 continue; | |
40 if (!styles_size[i].compare("Bold")) | |
41 *font_style |= gfx::Font::BOLD; | |
42 else if (!styles_size[i].compare("Italic")) | |
43 *font_style |= gfx::Font::ITALIC; | |
44 else | |
45 NOTREACHED(); | |
46 } | |
47 } | |
48 | |
49 // Returns the font style and size as a string. | |
50 std::string FontStyleAndSizeToString(int font_style, int font_size) { | |
51 std::string result; | |
52 if (font_style & gfx::Font::BOLD) | |
53 result += "Bold "; | |
54 if (font_style & gfx::Font::ITALIC) | |
55 result += "Italic "; | |
56 result += base::IntToString(font_size); | |
57 result += "px"; | |
58 return result; | |
59 } | |
60 | |
61 // Returns font description from |font_names|, |font_style|, and |font_size|. | |
62 std::string BuildFontDescription(const std::vector<std::string>& font_names, | |
63 int font_style, | |
64 int font_size) { | |
65 std::string description = JoinString(font_names, ','); | |
66 description += "," + FontStyleAndSizeToString(font_style, font_size); | |
67 return description; | |
68 } | |
69 | |
70 } // namespace | |
71 | |
72 namespace gfx { | |
73 | |
74 FontListImpl::FontListImpl(const std::string& font_description_string) | |
75 : font_description_string_(font_description_string), | |
76 common_height_(-1), | |
77 common_baseline_(-1), | |
78 font_style_(-1), | |
79 font_size_(-1) { | |
80 DCHECK(!font_description_string.empty()); | |
81 // DCHECK description string ends with "px" for size in pixel. | |
82 DCHECK(EndsWith(font_description_string, "px", true)); | |
83 } | |
84 | |
85 FontListImpl::FontListImpl(const std::vector<std::string>& font_names, | |
86 int font_style, | |
87 int font_size) | |
88 : font_description_string_(BuildFontDescription(font_names, font_style, | |
89 font_size)), | |
90 common_height_(-1), | |
91 common_baseline_(-1), | |
92 font_style_(font_style), | |
93 font_size_(font_size) { | |
94 DCHECK(!font_names.empty()); | |
95 DCHECK(!font_names[0].empty()); | |
96 } | |
97 | |
98 FontListImpl::FontListImpl(const std::vector<Font>& fonts) | |
99 : fonts_(fonts), | |
100 common_height_(-1), | |
101 common_baseline_(-1), | |
102 font_style_(-1), | |
103 font_size_(-1) { | |
104 DCHECK(!fonts.empty()); | |
105 font_style_ = fonts[0].GetStyle(); | |
106 font_size_ = fonts[0].GetFontSize(); | |
107 #if DCHECK_IS_ON() | |
108 for (size_t i = 1; i < fonts.size(); ++i) { | |
109 DCHECK_EQ(fonts[i].GetStyle(), font_style_); | |
110 DCHECK_EQ(fonts[i].GetFontSize(), font_size_); | |
111 } | |
112 #endif | |
113 } | |
114 | |
115 FontListImpl::FontListImpl(const Font& font) | |
116 : common_height_(-1), | |
117 common_baseline_(-1), | |
118 font_style_(-1), | |
119 font_size_(-1) { | |
120 fonts_.push_back(font); | |
121 } | |
122 | |
123 FontListImpl* FontListImpl::Derive(int size_delta, int font_style) const { | |
124 // If there is a font vector, derive from that. | |
125 if (!fonts_.empty()) { | |
126 std::vector<Font> fonts = fonts_; | |
127 for (size_t i = 0; i < fonts.size(); ++i) | |
128 fonts[i] = fonts[i].Derive(size_delta, font_style); | |
129 return new FontListImpl(fonts); | |
130 } | |
131 | |
132 // Otherwise, parse the font description string to derive from it. | |
133 std::vector<std::string> font_names; | |
134 int old_size; | |
135 int old_style; | |
136 ParseFontDescriptionString(font_description_string_, &font_names, | |
137 &old_style, &old_size); | |
138 const int size = std::max(1, old_size + size_delta); | |
139 return new FontListImpl(font_names, font_style, size); | |
140 } | |
141 | |
142 int FontListImpl::GetHeight() const { | |
143 if (common_height_ == -1) | |
144 CacheCommonFontHeightAndBaseline(); | |
145 return common_height_; | |
146 } | |
147 | |
148 int FontListImpl::GetBaseline() const { | |
149 if (common_baseline_ == -1) | |
150 CacheCommonFontHeightAndBaseline(); | |
151 return common_baseline_; | |
152 } | |
153 | |
154 int FontListImpl::GetCapHeight() const { | |
155 // Assume the primary font is used to render Latin characters. | |
156 return GetPrimaryFont().GetCapHeight(); | |
157 } | |
158 | |
159 int FontListImpl::GetExpectedTextWidth(int length) const { | |
160 // Rely on the primary font metrics for the time being. | |
161 return GetPrimaryFont().GetExpectedTextWidth(length); | |
162 } | |
163 | |
164 int FontListImpl::GetFontStyle() const { | |
165 if (font_style_ == -1) | |
166 CacheFontStyleAndSize(); | |
167 return font_style_; | |
168 } | |
169 | |
170 const std::string& FontListImpl::GetFontDescriptionString() const { | |
171 if (font_description_string_.empty()) { | |
172 DCHECK(!fonts_.empty()); | |
173 for (size_t i = 0; i < fonts_.size(); ++i) { | |
174 std::string name = fonts_[i].GetFontName(); | |
175 font_description_string_ += name; | |
176 font_description_string_ += ','; | |
177 } | |
178 // All fonts have the same style and size. | |
179 font_description_string_ += | |
180 FontStyleAndSizeToString(fonts_[0].GetStyle(), fonts_[0].GetFontSize()); | |
181 } | |
182 return font_description_string_; | |
183 } | |
184 | |
185 int FontListImpl::GetFontSize() const { | |
186 if (font_size_ == -1) | |
187 CacheFontStyleAndSize(); | |
188 return font_size_; | |
189 } | |
190 | |
191 const std::vector<Font>& FontListImpl::GetFonts() const { | |
192 if (fonts_.empty()) { | |
193 DCHECK(!font_description_string_.empty()); | |
194 | |
195 std::vector<std::string> font_names; | |
196 // It's possible that gfx::Font::UNDERLINE is specified and it's already | |
197 // stored in |font_style_| but |font_description_string_| doesn't have the | |
198 // underline info. So we should respect |font_style_| as long as it's | |
199 // valid. | |
200 int style = 0; | |
201 ParseFontDescriptionString(font_description_string_, &font_names, | |
202 &style, &font_size_); | |
203 if (font_style_ == -1) | |
204 font_style_ = style; | |
205 for (size_t i = 0; i < font_names.size(); ++i) { | |
206 DCHECK(!font_names[i].empty()); | |
207 | |
208 Font font(font_names[i], font_size_); | |
209 if (font_style_ == Font::NORMAL) | |
210 fonts_.push_back(font); | |
211 else | |
212 fonts_.push_back(font.Derive(0, font_style_)); | |
213 } | |
214 } | |
215 return fonts_; | |
216 } | |
217 | |
218 const Font& FontListImpl::GetPrimaryFont() const { | |
219 return GetFonts()[0]; | |
220 } | |
221 | |
222 FontListImpl::~FontListImpl() {} | |
223 | |
224 void FontListImpl::CacheCommonFontHeightAndBaseline() const { | |
225 int ascent = 0; | |
226 int descent = 0; | |
227 const std::vector<Font>& fonts = GetFonts(); | |
228 for (std::vector<Font>::const_iterator i = fonts.begin(); | |
229 i != fonts.end(); ++i) { | |
230 ascent = std::max(ascent, i->GetBaseline()); | |
231 descent = std::max(descent, i->GetHeight() - i->GetBaseline()); | |
232 } | |
233 common_height_ = ascent + descent; | |
234 common_baseline_ = ascent; | |
235 } | |
236 | |
237 void FontListImpl::CacheFontStyleAndSize() const { | |
238 if (!fonts_.empty()) { | |
239 font_style_ = fonts_[0].GetStyle(); | |
240 font_size_ = fonts_[0].GetFontSize(); | |
241 } else { | |
242 std::vector<std::string> font_names; | |
243 ParseFontDescriptionString(font_description_string_, &font_names, | |
244 &font_style_, &font_size_); | |
245 } | |
246 } | |
247 | |
248 } // namespace gfx | |
OLD | NEW |