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.
4
5#include "ui/gfx/font_list.h"
6
7#include <algorithm>
8#include <string>
9#include <vector>
10
11#include "base/strings/string_number_conversions.h"
12#include "base/strings/string_util.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace {
16
17// Helper function for comparing fonts for equality.
18std::string FontToString(const gfx::Font& font) {
19  std::string font_string = font.GetFontName();
20  font_string += "|";
21  font_string += base::IntToString(font.GetFontSize());
22  int style = font.GetStyle();
23  if (style & gfx::Font::BOLD)
24    font_string += "|bold";
25  if (style & gfx::Font::ITALIC)
26    font_string += "|italic";
27  if (style & gfx::Font::UNDERLINE)
28    font_string += "|underline";
29  return font_string;
30}
31
32}  // namespace
33
34namespace gfx {
35
36TEST(FontListTest, FontDescString_FromDescString) {
37  // Test init from font name style size string.
38  FontList font_list = FontList("Droid Sans serif, Sans serif, 10px");
39  EXPECT_EQ("Droid Sans serif, Sans serif, 10px",
40            font_list.GetFontDescriptionString());
41}
42
43TEST(FontListTest, FontDescString_FromFontNamesStyleAndSize) {
44  // Test init from font names, style and size.
45  std::vector<std::string> font_names;
46  font_names.push_back("Arial");
47  font_names.push_back("Droid Sans serif");
48  int font_style = Font::BOLD | Font::ITALIC | Font::UNDERLINE;
49  int font_size = 11;
50  FontList font_list = FontList(font_names, font_style, font_size);
51  // "Underline" doesn't appear in the font description string.
52  EXPECT_EQ("Arial,Droid Sans serif,Bold Italic 11px",
53            font_list.GetFontDescriptionString());
54}
55
56TEST(FontListTest, FontDescString_FromFont) {
57  // Test init from Font.
58  Font font("Arial", 8);
59  FontList font_list = FontList(font);
60  EXPECT_EQ("Arial,8px", font_list.GetFontDescriptionString());
61}
62
63TEST(FontListTest, FontDescString_FromFontWithNonNormalStyle) {
64  // Test init from Font with non-normal style.
65  Font font("Arial", 8);
66  FontList font_list = FontList(font.Derive(2, Font::BOLD));
67  EXPECT_EQ("Arial,Bold 10px", font_list.GetFontDescriptionString());
68
69  font_list = FontList(font.Derive(-2, Font::ITALIC));
70  EXPECT_EQ("Arial,Italic 6px", font_list.GetFontDescriptionString());
71
72  // "Underline" doesn't appear in the font description string.
73  font_list = FontList(font.Derive(-4, Font::UNDERLINE));
74  EXPECT_EQ("Arial,4px", font_list.GetFontDescriptionString());
75}
76
77TEST(FontListTest, FontDescString_FromFontVector) {
78  // Test init from Font vector.
79  Font font("Arial", 8);
80  Font font_1("Sans serif", 10);
81  std::vector<Font> fonts;
82  fonts.push_back(font.Derive(0, Font::BOLD));
83  fonts.push_back(font_1.Derive(-2, Font::BOLD));
84  FontList font_list = FontList(fonts);
85  EXPECT_EQ("Arial,Sans serif,Bold 8px", font_list.GetFontDescriptionString());
86}
87
88TEST(FontListTest, Fonts_FromDescString) {
89  // Test init from font name size string.
90  FontList font_list = FontList("serif,Sans serif, 13px");
91  const std::vector<Font>& fonts = font_list.GetFonts();
92  EXPECT_EQ(2U, fonts.size());
93  EXPECT_EQ("serif|13", FontToString(fonts[0]));
94  EXPECT_EQ("Sans serif|13", FontToString(fonts[1]));
95}
96
97TEST(FontListTest, Fonts_FromDescStringInFlexibleFormat) {
98  // Test init from font name size string with flexible format.
99  FontList font_list = FontList("  serif   ,   Sans serif ,   13px");
100  const std::vector<Font>& fonts = font_list.GetFonts();
101  EXPECT_EQ(2U, fonts.size());
102  EXPECT_EQ("serif|13", FontToString(fonts[0]));
103  EXPECT_EQ("Sans serif|13", FontToString(fonts[1]));
104}
105
106TEST(FontListTest, Fonts_FromDescStringWithStyleInFlexibleFormat) {
107  // Test init from font name style size string with flexible format.
108  FontList font_list = FontList("  serif  ,  Sans serif ,  Bold   "
109                                "  Italic   13px");
110  const std::vector<Font>& fonts = font_list.GetFonts();
111  EXPECT_EQ(2U, fonts.size());
112  EXPECT_EQ("serif|13|bold|italic", FontToString(fonts[0]));
113  EXPECT_EQ("Sans serif|13|bold|italic", FontToString(fonts[1]));
114}
115
116TEST(FontListTest, Fonts_FromFont) {
117  // Test init from Font.
118  Font font("Arial", 8);
119  FontList font_list = FontList(font);
120  const std::vector<Font>& fonts = font_list.GetFonts();
121  EXPECT_EQ(1U, fonts.size());
122  EXPECT_EQ("Arial|8", FontToString(fonts[0]));
123}
124
125TEST(FontListTest, Fonts_FromFontWithNonNormalStyle) {
126  // Test init from Font with non-normal style.
127  Font font("Arial", 8);
128  FontList font_list = FontList(font.Derive(2, Font::BOLD));
129  std::vector<Font> fonts = font_list.GetFonts();
130  EXPECT_EQ(1U, fonts.size());
131  EXPECT_EQ("Arial|10|bold", FontToString(fonts[0]));
132
133  font_list = FontList(font.Derive(-2, Font::ITALIC));
134  fonts = font_list.GetFonts();
135  EXPECT_EQ(1U, fonts.size());
136  EXPECT_EQ("Arial|6|italic", FontToString(fonts[0]));
137}
138
139TEST(FontListTest, Fonts_FromFontVector) {
140  // Test init from Font vector.
141  Font font("Arial", 8);
142  Font font_1("Sans serif", 10);
143  std::vector<Font> input_fonts;
144  input_fonts.push_back(font.Derive(0, Font::BOLD));
145  input_fonts.push_back(font_1.Derive(-2, Font::BOLD));
146  FontList font_list = FontList(input_fonts);
147  const std::vector<Font>& fonts = font_list.GetFonts();
148  EXPECT_EQ(2U, fonts.size());
149  EXPECT_EQ("Arial|8|bold", FontToString(fonts[0]));
150  EXPECT_EQ("Sans serif|8|bold", FontToString(fonts[1]));
151}
152
153TEST(FontListTest, Fonts_DescStringWithStyleInFlexibleFormat_RoundTrip) {
154  // Test round trip from font description string to font vector to
155  // font description string.
156  FontList font_list = FontList("  serif  ,  Sans serif ,  Bold   "
157                                "  Italic   13px");
158
159  const std::vector<Font>& fonts = font_list.GetFonts();
160  FontList font_list_1 = FontList(fonts);
161  const std::string& desc_str = font_list_1.GetFontDescriptionString();
162
163  EXPECT_EQ("serif,Sans serif,Bold Italic 13px", desc_str);
164}
165
166TEST(FontListTest, Fonts_FontVector_RoundTrip) {
167  // Test round trip from font vector to font description string to font vector.
168  Font font("Arial", 8);
169  Font font_1("Sans serif", 10);
170  std::vector<Font> input_fonts;
171  input_fonts.push_back(font.Derive(0, Font::BOLD));
172  input_fonts.push_back(font_1.Derive(-2, Font::BOLD));
173  FontList font_list = FontList(input_fonts);
174
175  const std::string& desc_string = font_list.GetFontDescriptionString();
176  FontList font_list_1 = FontList(desc_string);
177  const std::vector<Font>& round_trip_fonts = font_list_1.GetFonts();
178
179  EXPECT_EQ(2U, round_trip_fonts.size());
180  EXPECT_EQ("Arial|8|bold", FontToString(round_trip_fonts[0]));
181  EXPECT_EQ("Sans serif|8|bold", FontToString(round_trip_fonts[1]));
182}
183
184TEST(FontListTest, FontDescString_GetStyle) {
185  FontList font_list = FontList("Arial,Sans serif, 8px");
186  EXPECT_EQ(Font::NORMAL, font_list.GetFontStyle());
187
188  font_list = FontList("Arial,Sans serif,Bold 8px");
189  EXPECT_EQ(Font::BOLD, font_list.GetFontStyle());
190
191  font_list = FontList("Arial,Sans serif,Italic 8px");
192  EXPECT_EQ(Font::ITALIC, font_list.GetFontStyle());
193
194  font_list = FontList("Arial,Italic Bold 8px");
195  EXPECT_EQ(Font::BOLD | Font::ITALIC, font_list.GetFontStyle());
196}
197
198TEST(FontListTest, Fonts_GetStyle) {
199  std::vector<Font> fonts;
200  fonts.push_back(gfx::Font("Arial", 8));
201  fonts.push_back(gfx::Font("Sans serif", 8));
202  FontList font_list = FontList(fonts);
203  EXPECT_EQ(Font::NORMAL, font_list.GetFontStyle());
204  fonts[0] = fonts[0].Derive(0, Font::ITALIC | Font::BOLD);
205  fonts[1] = fonts[1].Derive(0, Font::ITALIC | Font::BOLD);
206  font_list = FontList(fonts);
207  EXPECT_EQ(Font::ITALIC | Font::BOLD, font_list.GetFontStyle());
208}
209
210TEST(FontListTest, FontDescString_Derive) {
211  FontList font_list = FontList("Arial,Sans serif,Bold Italic 8px");
212
213  FontList derived = font_list.Derive(10, Font::ITALIC | Font::UNDERLINE);
214  EXPECT_EQ("Arial,Sans serif,Italic 18px", derived.GetFontDescriptionString());
215  EXPECT_EQ(Font::ITALIC | Font::UNDERLINE, derived.GetFontStyle());
216
217  // FontList has a special case for Font::UNDERLINE.  See if the handling of
218  // Font::UNDERLINE in GetFonts() is okay or not.
219  derived.GetFonts();
220  EXPECT_EQ(Font::ITALIC | Font::UNDERLINE, derived.GetFontStyle());
221}
222
223TEST(FontListTest, Fonts_Derive) {
224  std::vector<Font> fonts;
225  fonts.push_back(gfx::Font("Arial", 8));
226  fonts.push_back(gfx::Font("Sans serif", 8));
227  FontList font_list = FontList(fonts);
228
229  FontList derived = font_list.Derive(5, Font::BOLD | Font::UNDERLINE);
230  const std::vector<Font>& derived_fonts = derived.GetFonts();
231
232  EXPECT_EQ(2U, derived_fonts.size());
233  EXPECT_EQ("Arial|13|bold|underline", FontToString(derived_fonts[0]));
234  EXPECT_EQ("Sans serif|13|bold|underline", FontToString(derived_fonts[1]));
235}
236
237TEST(FontListTest, FontDescString_DeriveWithSizeDelta) {
238  FontList font_list = FontList("Arial,Sans serif,Bold 18px");
239
240  FontList derived = font_list.DeriveWithSizeDelta(-8);
241  EXPECT_EQ("Arial,Sans serif,Bold 10px",
242            derived.GetFontDescriptionString());
243}
244
245TEST(FontListTest, Fonts_DeriveWithSizeDelta) {
246  std::vector<Font> fonts;
247  fonts.push_back(gfx::Font("Arial", 18).Derive(0, Font::ITALIC));
248  fonts.push_back(gfx::Font("Sans serif", 18).Derive(0, Font::ITALIC));
249  FontList font_list = FontList(fonts);
250
251  FontList derived = font_list.DeriveWithSizeDelta(-5);
252  const std::vector<Font>& derived_fonts = derived.GetFonts();
253
254  EXPECT_EQ(2U, derived_fonts.size());
255  EXPECT_EQ("Arial|13|italic", FontToString(derived_fonts[0]));
256  EXPECT_EQ("Sans serif|13|italic", FontToString(derived_fonts[1]));
257}
258
259TEST(FontListTest, Fonts_GetHeight_GetBaseline) {
260  // If a font list has only one font, the height and baseline must be the same.
261  Font font1("Arial", 16);
262  ASSERT_EQ("arial",
263            base::StringToLowerASCII(font1.GetActualFontNameForTesting()));
264  FontList font_list1("Arial, 16px");
265  EXPECT_EQ(font1.GetHeight(), font_list1.GetHeight());
266  EXPECT_EQ(font1.GetBaseline(), font_list1.GetBaseline());
267
268  // If there are two different fonts, the font list returns the max value
269  // for ascent and descent.
270  Font font2("Symbol", 16);
271  ASSERT_EQ("symbol",
272            base::StringToLowerASCII(font2.GetActualFontNameForTesting()));
273  EXPECT_NE(font1.GetBaseline(), font2.GetBaseline());
274  EXPECT_NE(font1.GetHeight() - font1.GetBaseline(),
275            font2.GetHeight() - font2.GetBaseline());
276  std::vector<Font> fonts;
277  fonts.push_back(font1);
278  fonts.push_back(font2);
279  FontList font_list_mix(fonts);
280  // ascent of FontList == max(ascent of Fonts)
281  EXPECT_EQ(std::max(font1.GetHeight() - font1.GetBaseline(),
282                     font2.GetHeight() - font2.GetBaseline()),
283            font_list_mix.GetHeight() - font_list_mix.GetBaseline());
284  // descent of FontList == max(descent of Fonts)
285  EXPECT_EQ(std::max(font1.GetBaseline(), font2.GetBaseline()),
286            font_list_mix.GetBaseline());
287}
288
289TEST(FontListTest, Fonts_DeriveWithHeightUpperBound) {
290  std::vector<Font> fonts;
291
292  fonts.push_back(gfx::Font("Arial", 18));
293  fonts.push_back(gfx::Font("Sans serif", 18));
294  fonts.push_back(gfx::Font("Symbol", 18));
295  FontList font_list = FontList(fonts);
296
297  // A smaller upper bound should derive a font list with a smaller height.
298  const int height_1 = font_list.GetHeight() - 5;
299  FontList derived_1 = font_list.DeriveWithHeightUpperBound(height_1);
300  EXPECT_LE(derived_1.GetHeight(), height_1);
301  EXPECT_LT(derived_1.GetHeight(), font_list.GetHeight());
302  EXPECT_LT(derived_1.GetFontSize(), font_list.GetFontSize());
303
304  // A larger upper bound should not change the height of the font list.
305  const int height_2 = font_list.GetHeight() + 5;
306  FontList derived_2 = font_list.DeriveWithHeightUpperBound(height_2);
307  EXPECT_LE(derived_2.GetHeight(), height_2);
308  EXPECT_EQ(font_list.GetHeight(), derived_2.GetHeight());
309  EXPECT_EQ(font_list.GetFontSize(), derived_2.GetFontSize());
310}
311
312}  // namespace gfx
313