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_render_params.h"
7 #include "base/files/file_path.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/logging.h"
10 #include "base/macros.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gfx/font.h"
13 #include "ui/gfx/linux_font_delegate.h"
14 #include "ui/gfx/pango_util.h"
15 #include "ui/gfx/test/fontconfig_util_linux.h"
21 // Implementation of LinuxFontDelegate that returns a canned FontRenderParams
22 // struct. This is used to isolate tests from the system's local configuration.
23 class TestFontDelegate
: public LinuxFontDelegate
{
26 virtual ~TestFontDelegate() {}
28 void set_params(const FontRenderParams
& params
) { params_
= params
; }
30 virtual FontRenderParams
GetDefaultFontRenderParams() const OVERRIDE
{
33 virtual scoped_ptr
<ScopedPangoFontDescription
>
34 GetDefaultPangoFontDescription() const OVERRIDE
{
36 return scoped_ptr
<ScopedPangoFontDescription
>();
38 virtual double GetFontDPI() const OVERRIDE
{
44 FontRenderParams params_
;
46 DISALLOW_COPY_AND_ASSIGN(TestFontDelegate
);
49 // Loads the first system font defined by fontconfig_util_linux.h with a base
50 // filename of |basename|. Case is ignored.
51 bool LoadSystemFont(const std::string
& basename
) {
52 for (size_t i
= 0; i
< kNumSystemFontsForFontconfig
; ++i
) {
53 base::FilePath
path(gfx::kSystemFontsForFontconfig
[i
]);
54 if (strcasecmp(path
.BaseName().value().c_str(), basename
.c_str()) == 0)
55 return LoadFontIntoFontconfig(path
);
57 LOG(ERROR
) << "Unable to find system font named " << basename
;
63 class FontRenderParamsTest
: public testing::Test
{
65 FontRenderParamsTest() {
67 CHECK(temp_dir_
.CreateUniqueTempDir());
68 original_font_delegate_
= LinuxFontDelegate::instance();
69 LinuxFontDelegate::SetInstance(&test_font_delegate_
);
72 virtual ~FontRenderParamsTest() {
73 LinuxFontDelegate::SetInstance(
74 const_cast<LinuxFontDelegate
*>(original_font_delegate_
));
79 base::ScopedTempDir temp_dir_
;
80 const LinuxFontDelegate
* original_font_delegate_
;
81 TestFontDelegate test_font_delegate_
;
84 DISALLOW_COPY_AND_ASSIGN(FontRenderParamsTest
);
87 TEST_F(FontRenderParamsTest
, Default
) {
88 // Fontconfig needs to know about at least one font to return a match.
89 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
90 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
91 std::string(kFontconfigFileHeader
) +
92 kFontconfigMatchHeader
+
93 CreateFontconfigEditStanza("antialias", "bool", "true") +
94 CreateFontconfigEditStanza("autohint", "bool", "false") +
95 CreateFontconfigEditStanza("hinting", "bool", "true") +
96 CreateFontconfigEditStanza("hintstyle", "const", "hintfull") +
97 CreateFontconfigEditStanza("rgba", "const", "rgb") +
98 kFontconfigMatchFooter
+
99 kFontconfigFileFooter
));
101 FontRenderParams params
= GetFontRenderParams(
102 FontRenderParamsQuery(true), NULL
);
103 EXPECT_TRUE(params
.antialiasing
);
104 EXPECT_FALSE(params
.autohinter
);
105 EXPECT_TRUE(params
.use_bitmaps
);
106 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
107 EXPECT_FALSE(params
.subpixel_positioning
);
108 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
109 params
.subpixel_rendering
);
112 TEST_F(FontRenderParamsTest
, Size
) {
113 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
114 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
115 std::string(kFontconfigFileHeader
) +
116 kFontconfigMatchHeader
+
117 CreateFontconfigEditStanza("antialias", "bool", "true") +
118 CreateFontconfigEditStanza("hinting", "bool", "true") +
119 CreateFontconfigEditStanza("hintstyle", "const", "hintfull") +
120 CreateFontconfigEditStanza("rgba", "const", "none") +
121 kFontconfigMatchFooter
+
122 kFontconfigMatchHeader
+
123 CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") +
124 CreateFontconfigEditStanza("antialias", "bool", "false") +
125 kFontconfigMatchFooter
+
126 kFontconfigMatchHeader
+
127 CreateFontconfigTestStanza("size", "more_eq", "double", "20") +
128 CreateFontconfigEditStanza("hintstyle", "const", "hintslight") +
129 CreateFontconfigEditStanza("rgba", "const", "rgb") +
130 kFontconfigMatchFooter
+
131 kFontconfigFileFooter
));
133 // The defaults should be used when the supplied size isn't matched by the
134 // second or third blocks.
135 FontRenderParamsQuery
query(false);
136 query
.pixel_size
= 12;
137 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
138 EXPECT_TRUE(params
.antialiasing
);
139 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
140 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
141 params
.subpixel_rendering
);
143 query
.pixel_size
= 10;
144 params
= GetFontRenderParams(query
, NULL
);
145 EXPECT_FALSE(params
.antialiasing
);
146 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
147 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
148 params
.subpixel_rendering
);
150 query
.pixel_size
= 0;
151 query
.point_size
= 20;
152 params
= GetFontRenderParams(query
, NULL
);
153 EXPECT_TRUE(params
.antialiasing
);
154 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
155 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
156 params
.subpixel_rendering
);
159 TEST_F(FontRenderParamsTest
, Style
) {
160 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
161 // Load a config that disables subpixel rendering for bold text and disables
162 // hinting for italic text.
163 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
164 std::string(kFontconfigFileHeader
) +
165 kFontconfigMatchHeader
+
166 CreateFontconfigEditStanza("antialias", "bool", "true") +
167 CreateFontconfigEditStanza("hinting", "bool", "true") +
168 CreateFontconfigEditStanza("hintstyle", "const", "hintslight") +
169 CreateFontconfigEditStanza("rgba", "const", "rgb") +
170 kFontconfigMatchFooter
+
171 kFontconfigMatchHeader
+
172 CreateFontconfigTestStanza("weight", "eq", "const", "bold") +
173 CreateFontconfigEditStanza("rgba", "const", "none") +
174 kFontconfigMatchFooter
+
175 kFontconfigMatchHeader
+
176 CreateFontconfigTestStanza("slant", "eq", "const", "italic") +
177 CreateFontconfigEditStanza("hinting", "bool", "false") +
178 kFontconfigMatchFooter
+
179 kFontconfigFileFooter
));
181 FontRenderParamsQuery
query(false);
182 query
.style
= Font::NORMAL
;
183 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
184 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
185 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
186 params
.subpixel_rendering
);
188 query
.style
= Font::BOLD
;
189 params
= GetFontRenderParams(query
, NULL
);
190 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
191 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
192 params
.subpixel_rendering
);
194 query
.style
= Font::ITALIC
;
195 params
= GetFontRenderParams(query
, NULL
);
196 EXPECT_EQ(FontRenderParams::HINTING_NONE
, params
.hinting
);
197 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
198 params
.subpixel_rendering
);
200 query
.style
= Font::BOLD
| Font::ITALIC
;
201 params
= GetFontRenderParams(query
, NULL
);
202 EXPECT_EQ(FontRenderParams::HINTING_NONE
, params
.hinting
);
203 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
204 params
.subpixel_rendering
);
207 TEST_F(FontRenderParamsTest
, Scalable
) {
208 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
209 // Load a config that only enables antialiasing for scalable fonts.
210 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
211 std::string(kFontconfigFileHeader
) +
212 kFontconfigMatchHeader
+
213 CreateFontconfigEditStanza("antialias", "bool", "false") +
214 kFontconfigMatchFooter
+
215 kFontconfigMatchHeader
+
216 CreateFontconfigTestStanza("scalable", "eq", "bool", "true") +
217 CreateFontconfigEditStanza("antialias", "bool", "true") +
218 kFontconfigMatchFooter
+
219 kFontconfigFileFooter
));
221 // Check that we specifically ask how scalable fonts should be rendered.
222 FontRenderParams params
= GetFontRenderParams(
223 FontRenderParamsQuery(false), NULL
);
224 EXPECT_TRUE(params
.antialiasing
);
227 TEST_F(FontRenderParamsTest
, UseBitmaps
) {
228 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
229 // Load a config that enables embedded bitmaps for fonts <= 10 pixels.
230 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
231 std::string(kFontconfigFileHeader
) +
232 kFontconfigMatchHeader
+
233 CreateFontconfigEditStanza("embeddedbitmap", "bool", "false") +
234 kFontconfigMatchFooter
+
235 kFontconfigMatchHeader
+
236 CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") +
237 CreateFontconfigEditStanza("embeddedbitmap", "bool", "true") +
238 kFontconfigMatchFooter
+
239 kFontconfigFileFooter
));
241 FontRenderParamsQuery
query(false);
242 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
243 EXPECT_FALSE(params
.use_bitmaps
);
245 query
.pixel_size
= 5;
246 params
= GetFontRenderParams(query
, NULL
);
247 EXPECT_TRUE(params
.use_bitmaps
);
250 TEST_F(FontRenderParamsTest
, ForceFullHintingWhenAntialiasingIsDisabled
) {
251 // Load a config that disables antialiasing and hinting while requesting
252 // subpixel rendering.
253 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
254 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
255 std::string(kFontconfigFileHeader
) +
256 kFontconfigMatchHeader
+
257 CreateFontconfigEditStanza("antialias", "bool", "false") +
258 CreateFontconfigEditStanza("hinting", "bool", "false") +
259 CreateFontconfigEditStanza("hintstyle", "const", "hintnone") +
260 CreateFontconfigEditStanza("rgba", "const", "rgb") +
261 kFontconfigMatchFooter
+
262 kFontconfigFileFooter
));
264 // Full hinting should be forced. See the comment in GetFontRenderParams() for
266 FontRenderParams params
= GetFontRenderParams(
267 FontRenderParamsQuery(false), NULL
);
268 EXPECT_FALSE(params
.antialiasing
);
269 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
270 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
271 params
.subpixel_rendering
);
272 EXPECT_FALSE(params
.subpixel_positioning
);
275 TEST_F(FontRenderParamsTest
, OnlySetConfiguredValues
) {
276 // Configure the LinuxFontDelegate (which queries GtkSettings on desktop
277 // Linux) to request subpixel rendering.
278 FontRenderParams system_params
;
279 system_params
.subpixel_rendering
= FontRenderParams::SUBPIXEL_RENDERING_RGB
;
280 test_font_delegate_
.set_params(system_params
);
282 // Load a Fontconfig config that enables antialiasing but doesn't say anything
283 // about subpixel rendering.
284 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
285 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
286 std::string(kFontconfigFileHeader
) +
287 kFontconfigMatchHeader
+
288 CreateFontconfigEditStanza("antialias", "bool", "true") +
289 kFontconfigMatchFooter
+
290 kFontconfigFileFooter
));
292 // The subpixel rendering setting from the delegate should make it through.
293 FontRenderParams params
= GetFontRenderParams(
294 FontRenderParamsQuery(false), NULL
);
295 EXPECT_EQ(system_params
.subpixel_rendering
, params
.subpixel_rendering
);
298 TEST_F(FontRenderParamsTest
, NoFontconfigMatch
) {
299 // Don't load a Fontconfig configuration.
300 FontRenderParams system_params
;
301 system_params
.antialiasing
= true;
302 system_params
.hinting
= FontRenderParams::HINTING_MEDIUM
;
303 system_params
.subpixel_rendering
= FontRenderParams::SUBPIXEL_RENDERING_RGB
;
304 test_font_delegate_
.set_params(system_params
);
306 FontRenderParamsQuery
query(false);
307 query
.families
.push_back("Arial");
308 query
.families
.push_back("Times New Roman");
309 query
.pixel_size
= 10;
310 std::string suggested_family
;
311 FontRenderParams params
= GetFontRenderParams(query
, &suggested_family
);
313 // The system params and the first requested family should be returned.
314 EXPECT_EQ(system_params
.antialiasing
, params
.antialiasing
);
315 EXPECT_EQ(system_params
.hinting
, params
.hinting
);
316 EXPECT_EQ(system_params
.subpixel_rendering
, params
.subpixel_rendering
);
317 EXPECT_EQ(query
.families
[0], suggested_family
);
320 TEST_F(FontRenderParamsTest
, MissingFamily
) {
321 // With Arial and Verdana installed, request (in order) Helvetica, Arial, and
322 // Verdana and check that Arial is returned.
323 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
324 ASSERT_TRUE(LoadSystemFont("verdana.ttf"));
325 FontRenderParamsQuery
query(false);
326 query
.families
.push_back("Helvetica");
327 query
.families
.push_back("Arial");
328 query
.families
.push_back("Verdana");
329 std::string suggested_family
;
330 GetFontRenderParams(query
, &suggested_family
);
331 EXPECT_EQ("Arial", suggested_family
);
334 TEST_F(FontRenderParamsTest
, SubstituteFamily
) {
335 // Configure Fontconfig to use Verdana for both Helvetica and Arial.
336 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
337 ASSERT_TRUE(LoadSystemFont("verdana.ttf"));
338 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
339 std::string(kFontconfigFileHeader
) +
340 CreateFontconfigAliasStanza("Helvetica", "Verdana") +
341 kFontconfigMatchHeader
+
342 CreateFontconfigTestStanza("family", "eq", "string", "Arial") +
343 CreateFontconfigEditStanza("family", "string", "Verdana") +
344 kFontconfigMatchFooter
+
345 kFontconfigFileFooter
));
347 FontRenderParamsQuery
query(false);
348 query
.families
.push_back("Helvetica");
349 std::string suggested_family
;
350 GetFontRenderParams(query
, &suggested_family
);
351 EXPECT_EQ("Verdana", suggested_family
);
353 query
.families
.clear();
354 query
.families
.push_back("Arial");
355 suggested_family
.clear();
356 GetFontRenderParams(query
, &suggested_family
);
357 EXPECT_EQ("Verdana", suggested_family
);