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_
);
70 ClearFontRenderParamsCacheForTest();
73 virtual ~FontRenderParamsTest() {
74 LinuxFontDelegate::SetInstance(
75 const_cast<LinuxFontDelegate
*>(original_font_delegate_
));
80 base::ScopedTempDir temp_dir_
;
81 const LinuxFontDelegate
* original_font_delegate_
;
82 TestFontDelegate test_font_delegate_
;
85 DISALLOW_COPY_AND_ASSIGN(FontRenderParamsTest
);
88 TEST_F(FontRenderParamsTest
, Default
) {
89 // Fontconfig needs to know about at least one font to return a match.
90 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
91 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
92 std::string(kFontconfigFileHeader
) +
93 kFontconfigMatchHeader
+
94 CreateFontconfigEditStanza("antialias", "bool", "true") +
95 CreateFontconfigEditStanza("autohint", "bool", "false") +
96 CreateFontconfigEditStanza("hinting", "bool", "true") +
97 CreateFontconfigEditStanza("hintstyle", "const", "hintfull") +
98 CreateFontconfigEditStanza("rgba", "const", "rgb") +
99 kFontconfigMatchFooter
+
100 kFontconfigFileFooter
));
102 FontRenderParams params
= GetFontRenderParams(
103 FontRenderParamsQuery(true), NULL
);
104 EXPECT_TRUE(params
.antialiasing
);
105 EXPECT_FALSE(params
.autohinter
);
106 EXPECT_TRUE(params
.use_bitmaps
);
107 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
108 EXPECT_FALSE(params
.subpixel_positioning
);
109 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
110 params
.subpixel_rendering
);
113 TEST_F(FontRenderParamsTest
, Size
) {
114 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
115 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
116 std::string(kFontconfigFileHeader
) +
117 kFontconfigMatchHeader
+
118 CreateFontconfigEditStanza("antialias", "bool", "true") +
119 CreateFontconfigEditStanza("hinting", "bool", "true") +
120 CreateFontconfigEditStanza("hintstyle", "const", "hintfull") +
121 CreateFontconfigEditStanza("rgba", "const", "none") +
122 kFontconfigMatchFooter
+
123 kFontconfigMatchHeader
+
124 CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") +
125 CreateFontconfigEditStanza("antialias", "bool", "false") +
126 kFontconfigMatchFooter
+
127 kFontconfigMatchHeader
+
128 CreateFontconfigTestStanza("size", "more_eq", "double", "20") +
129 CreateFontconfigEditStanza("hintstyle", "const", "hintslight") +
130 CreateFontconfigEditStanza("rgba", "const", "rgb") +
131 kFontconfigMatchFooter
+
132 kFontconfigFileFooter
));
134 // The defaults should be used when the supplied size isn't matched by the
135 // second or third blocks.
136 FontRenderParamsQuery
query(false);
137 query
.pixel_size
= 12;
138 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
139 EXPECT_TRUE(params
.antialiasing
);
140 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
141 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
142 params
.subpixel_rendering
);
144 query
.pixel_size
= 10;
145 params
= GetFontRenderParams(query
, NULL
);
146 EXPECT_FALSE(params
.antialiasing
);
147 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
148 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
149 params
.subpixel_rendering
);
151 query
.pixel_size
= 0;
152 query
.point_size
= 20;
153 params
= GetFontRenderParams(query
, NULL
);
154 EXPECT_TRUE(params
.antialiasing
);
155 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
156 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
157 params
.subpixel_rendering
);
160 TEST_F(FontRenderParamsTest
, Style
) {
161 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
162 // Load a config that disables subpixel rendering for bold text and disables
163 // hinting for italic text.
164 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
165 std::string(kFontconfigFileHeader
) +
166 kFontconfigMatchHeader
+
167 CreateFontconfigEditStanza("antialias", "bool", "true") +
168 CreateFontconfigEditStanza("hinting", "bool", "true") +
169 CreateFontconfigEditStanza("hintstyle", "const", "hintslight") +
170 CreateFontconfigEditStanza("rgba", "const", "rgb") +
171 kFontconfigMatchFooter
+
172 kFontconfigMatchHeader
+
173 CreateFontconfigTestStanza("weight", "eq", "const", "bold") +
174 CreateFontconfigEditStanza("rgba", "const", "none") +
175 kFontconfigMatchFooter
+
176 kFontconfigMatchHeader
+
177 CreateFontconfigTestStanza("slant", "eq", "const", "italic") +
178 CreateFontconfigEditStanza("hinting", "bool", "false") +
179 kFontconfigMatchFooter
+
180 kFontconfigFileFooter
));
182 FontRenderParamsQuery
query(false);
183 query
.style
= Font::NORMAL
;
184 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
185 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
186 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
187 params
.subpixel_rendering
);
189 query
.style
= Font::BOLD
;
190 params
= GetFontRenderParams(query
, NULL
);
191 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
192 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
193 params
.subpixel_rendering
);
195 query
.style
= Font::ITALIC
;
196 params
= GetFontRenderParams(query
, NULL
);
197 EXPECT_EQ(FontRenderParams::HINTING_NONE
, params
.hinting
);
198 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
199 params
.subpixel_rendering
);
201 query
.style
= Font::BOLD
| Font::ITALIC
;
202 params
= GetFontRenderParams(query
, NULL
);
203 EXPECT_EQ(FontRenderParams::HINTING_NONE
, params
.hinting
);
204 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
205 params
.subpixel_rendering
);
208 TEST_F(FontRenderParamsTest
, Scalable
) {
209 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
210 // Load a config that only enables antialiasing for scalable fonts.
211 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
212 std::string(kFontconfigFileHeader
) +
213 kFontconfigMatchHeader
+
214 CreateFontconfigEditStanza("antialias", "bool", "false") +
215 kFontconfigMatchFooter
+
216 kFontconfigMatchHeader
+
217 CreateFontconfigTestStanza("scalable", "eq", "bool", "true") +
218 CreateFontconfigEditStanza("antialias", "bool", "true") +
219 kFontconfigMatchFooter
+
220 kFontconfigFileFooter
));
222 // Check that we specifically ask how scalable fonts should be rendered.
223 FontRenderParams params
= GetFontRenderParams(
224 FontRenderParamsQuery(false), NULL
);
225 EXPECT_TRUE(params
.antialiasing
);
228 TEST_F(FontRenderParamsTest
, UseBitmaps
) {
229 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
230 // Load a config that enables embedded bitmaps for fonts <= 10 pixels.
231 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
232 std::string(kFontconfigFileHeader
) +
233 kFontconfigMatchHeader
+
234 CreateFontconfigEditStanza("embeddedbitmap", "bool", "false") +
235 kFontconfigMatchFooter
+
236 kFontconfigMatchHeader
+
237 CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") +
238 CreateFontconfigEditStanza("embeddedbitmap", "bool", "true") +
239 kFontconfigMatchFooter
+
240 kFontconfigFileFooter
));
242 FontRenderParamsQuery
query(false);
243 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
244 EXPECT_FALSE(params
.use_bitmaps
);
246 query
.pixel_size
= 5;
247 params
= GetFontRenderParams(query
, NULL
);
248 EXPECT_TRUE(params
.use_bitmaps
);
251 TEST_F(FontRenderParamsTest
, ForceFullHintingWhenAntialiasingIsDisabled
) {
252 // Load a config that disables antialiasing and hinting while requesting
253 // subpixel rendering.
254 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
255 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
256 std::string(kFontconfigFileHeader
) +
257 kFontconfigMatchHeader
+
258 CreateFontconfigEditStanza("antialias", "bool", "false") +
259 CreateFontconfigEditStanza("hinting", "bool", "false") +
260 CreateFontconfigEditStanza("hintstyle", "const", "hintnone") +
261 CreateFontconfigEditStanza("rgba", "const", "rgb") +
262 kFontconfigMatchFooter
+
263 kFontconfigFileFooter
));
265 // Full hinting should be forced. See the comment in GetFontRenderParams() for
267 FontRenderParams params
= GetFontRenderParams(
268 FontRenderParamsQuery(false), NULL
);
269 EXPECT_FALSE(params
.antialiasing
);
270 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
271 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
272 params
.subpixel_rendering
);
273 EXPECT_FALSE(params
.subpixel_positioning
);
276 #if defined(OS_CHROMEOS)
277 TEST_F(FontRenderParamsTest
, ForceSubpixelPositioning
) {
279 FontRenderParams params
=
280 GetFontRenderParams(FontRenderParamsQuery(false), NULL
);
281 EXPECT_TRUE(params
.antialiasing
);
282 EXPECT_FALSE(params
.subpixel_positioning
);
283 SetFontRenderParamsDeviceScaleFactor(1.0f
);
285 ClearFontRenderParamsCacheForTest();
286 SetFontRenderParamsDeviceScaleFactor(1.25f
);
287 // Subpixel positioning should be forced.
289 FontRenderParams params
=
290 GetFontRenderParams(FontRenderParamsQuery(false), NULL
);
291 EXPECT_TRUE(params
.antialiasing
);
292 EXPECT_TRUE(params
.subpixel_positioning
);
293 SetFontRenderParamsDeviceScaleFactor(1.0f
);
298 TEST_F(FontRenderParamsTest
, OnlySetConfiguredValues
) {
299 // Configure the LinuxFontDelegate (which queries GtkSettings on desktop
300 // Linux) to request subpixel rendering.
301 FontRenderParams system_params
;
302 system_params
.subpixel_rendering
= FontRenderParams::SUBPIXEL_RENDERING_RGB
;
303 test_font_delegate_
.set_params(system_params
);
305 // Load a Fontconfig config that enables antialiasing but doesn't say anything
306 // about subpixel rendering.
307 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
308 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
309 std::string(kFontconfigFileHeader
) +
310 kFontconfigMatchHeader
+
311 CreateFontconfigEditStanza("antialias", "bool", "true") +
312 kFontconfigMatchFooter
+
313 kFontconfigFileFooter
));
315 // The subpixel rendering setting from the delegate should make it through.
316 FontRenderParams params
= GetFontRenderParams(
317 FontRenderParamsQuery(false), NULL
);
318 EXPECT_EQ(system_params
.subpixel_rendering
, params
.subpixel_rendering
);
321 TEST_F(FontRenderParamsTest
, NoFontconfigMatch
) {
322 // Don't load a Fontconfig configuration.
323 FontRenderParams system_params
;
324 system_params
.antialiasing
= true;
325 system_params
.hinting
= FontRenderParams::HINTING_MEDIUM
;
326 system_params
.subpixel_rendering
= FontRenderParams::SUBPIXEL_RENDERING_RGB
;
327 test_font_delegate_
.set_params(system_params
);
329 FontRenderParamsQuery
query(false);
330 query
.families
.push_back("Arial");
331 query
.families
.push_back("Times New Roman");
332 query
.pixel_size
= 10;
333 std::string suggested_family
;
334 FontRenderParams params
= GetFontRenderParams(query
, &suggested_family
);
336 // The system params and the first requested family should be returned.
337 EXPECT_EQ(system_params
.antialiasing
, params
.antialiasing
);
338 EXPECT_EQ(system_params
.hinting
, params
.hinting
);
339 EXPECT_EQ(system_params
.subpixel_rendering
, params
.subpixel_rendering
);
340 EXPECT_EQ(query
.families
[0], suggested_family
);
343 TEST_F(FontRenderParamsTest
, MissingFamily
) {
344 // With Arial and Verdana installed, request (in order) Helvetica, Arial, and
345 // Verdana and check that Arial is returned.
346 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
347 ASSERT_TRUE(LoadSystemFont("verdana.ttf"));
348 FontRenderParamsQuery
query(false);
349 query
.families
.push_back("Helvetica");
350 query
.families
.push_back("Arial");
351 query
.families
.push_back("Verdana");
352 std::string suggested_family
;
353 GetFontRenderParams(query
, &suggested_family
);
354 EXPECT_EQ("Arial", suggested_family
);
357 TEST_F(FontRenderParamsTest
, SubstituteFamily
) {
358 // Configure Fontconfig to use Verdana for both Helvetica and Arial.
359 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
360 ASSERT_TRUE(LoadSystemFont("verdana.ttf"));
361 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
362 std::string(kFontconfigFileHeader
) +
363 CreateFontconfigAliasStanza("Helvetica", "Verdana") +
364 kFontconfigMatchHeader
+
365 CreateFontconfigTestStanza("family", "eq", "string", "Arial") +
366 CreateFontconfigEditStanza("family", "string", "Verdana") +
367 kFontconfigMatchFooter
+
368 kFontconfigFileFooter
));
370 FontRenderParamsQuery
query(false);
371 query
.families
.push_back("Helvetica");
372 std::string suggested_family
;
373 GetFontRenderParams(query
, &suggested_family
);
374 EXPECT_EQ("Verdana", suggested_family
);
376 query
.families
.clear();
377 query
.families
.push_back("Arial");
378 suggested_family
.clear();
379 GetFontRenderParams(query
, &suggested_family
);
380 EXPECT_EQ("Verdana", suggested_family
);