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 ~TestFontDelegate() override
{}
28 void set_params(const FontRenderParams
& params
) { params_
= params
; }
30 FontRenderParams
GetDefaultFontRenderParams() const override
{
33 scoped_ptr
<ScopedPangoFontDescription
> GetDefaultPangoFontDescription()
38 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. FcFontMatch() requires there to be
51 // at least one font present.
52 bool LoadSystemFont(const std::string
& basename
) {
53 for (size_t i
= 0; i
< kNumSystemFontsForFontconfig
; ++i
) {
54 base::FilePath
path(gfx::kSystemFontsForFontconfig
[i
]);
55 if (strcasecmp(path
.BaseName().value().c_str(), basename
.c_str()) == 0)
56 return LoadFontIntoFontconfig(path
);
58 LOG(ERROR
) << "Unable to find system font named " << basename
;
64 class FontRenderParamsTest
: public testing::Test
{
66 FontRenderParamsTest() {
68 CHECK(temp_dir_
.CreateUniqueTempDir());
69 original_font_delegate_
= LinuxFontDelegate::instance();
70 LinuxFontDelegate::SetInstance(&test_font_delegate_
);
71 ClearFontRenderParamsCacheForTest();
74 ~FontRenderParamsTest() override
{
75 LinuxFontDelegate::SetInstance(
76 const_cast<LinuxFontDelegate
*>(original_font_delegate_
));
81 base::ScopedTempDir temp_dir_
;
82 const LinuxFontDelegate
* original_font_delegate_
;
83 TestFontDelegate test_font_delegate_
;
86 DISALLOW_COPY_AND_ASSIGN(FontRenderParamsTest
);
89 TEST_F(FontRenderParamsTest
, Default
) {
90 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
91 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
92 std::string(kFontconfigFileHeader
) +
93 // Specify the desired defaults via a font match rather than a pattern
94 // match (since this is the style generally used in /etc/fonts/conf.d).
95 kFontconfigMatchFontHeader
+
96 CreateFontconfigEditStanza("antialias", "bool", "true") +
97 CreateFontconfigEditStanza("autohint", "bool", "true") +
98 CreateFontconfigEditStanza("hinting", "bool", "true") +
99 CreateFontconfigEditStanza("hintstyle", "const", "hintslight") +
100 CreateFontconfigEditStanza("rgba", "const", "rgb") +
101 kFontconfigMatchFooter
+
102 // Add a font match for Arial. Since it specifies a family, it shouldn't
103 // take effect when querying default settings.
104 kFontconfigMatchFontHeader
+
105 CreateFontconfigTestStanza("family", "eq", "string", "Arial") +
106 CreateFontconfigEditStanza("antialias", "bool", "true") +
107 CreateFontconfigEditStanza("autohint", "bool", "false") +
108 CreateFontconfigEditStanza("hinting", "bool", "true") +
109 CreateFontconfigEditStanza("hintstyle", "const", "hintfull") +
110 CreateFontconfigEditStanza("rgba", "const", "none") +
111 kFontconfigMatchFooter
+
112 // Add font matches for fonts between 10 and 20 points or pixels. Since
113 // they specify sizes, they also should not affect the defaults.
114 kFontconfigMatchFontHeader
+
115 CreateFontconfigTestStanza("size", "more_eq", "double", "10.0") +
116 CreateFontconfigTestStanza("size", "less_eq", "double", "20.0") +
117 CreateFontconfigEditStanza("antialias", "bool", "false") +
118 kFontconfigMatchFooter
+
119 kFontconfigMatchFontHeader
+
120 CreateFontconfigTestStanza("pixel_size", "more_eq", "double", "10.0") +
121 CreateFontconfigTestStanza("pixel_size", "less_eq", "double", "20.0") +
122 CreateFontconfigEditStanza("antialias", "bool", "false") +
123 kFontconfigMatchFooter
+
124 kFontconfigFileFooter
));
126 FontRenderParams params
= GetFontRenderParams(
127 FontRenderParamsQuery(true), NULL
);
128 EXPECT_TRUE(params
.antialiasing
);
129 EXPECT_TRUE(params
.autohinter
);
130 EXPECT_TRUE(params
.use_bitmaps
);
131 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
132 EXPECT_FALSE(params
.subpixel_positioning
);
133 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
134 params
.subpixel_rendering
);
137 TEST_F(FontRenderParamsTest
, Size
) {
138 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
139 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
140 std::string(kFontconfigFileHeader
) +
141 kFontconfigMatchPatternHeader
+
142 CreateFontconfigEditStanza("antialias", "bool", "true") +
143 CreateFontconfigEditStanza("hinting", "bool", "true") +
144 CreateFontconfigEditStanza("hintstyle", "const", "hintfull") +
145 CreateFontconfigEditStanza("rgba", "const", "none") +
146 kFontconfigMatchFooter
+
147 kFontconfigMatchPatternHeader
+
148 CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") +
149 CreateFontconfigEditStanza("antialias", "bool", "false") +
150 kFontconfigMatchFooter
+
151 kFontconfigMatchPatternHeader
+
152 CreateFontconfigTestStanza("size", "more_eq", "double", "20") +
153 CreateFontconfigEditStanza("hintstyle", "const", "hintslight") +
154 CreateFontconfigEditStanza("rgba", "const", "rgb") +
155 kFontconfigMatchFooter
+
156 kFontconfigFileFooter
));
158 // The defaults should be used when the supplied size isn't matched by the
159 // second or third blocks.
160 FontRenderParamsQuery
query(false);
161 query
.pixel_size
= 12;
162 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
163 EXPECT_TRUE(params
.antialiasing
);
164 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
165 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
166 params
.subpixel_rendering
);
168 query
.pixel_size
= 10;
169 params
= GetFontRenderParams(query
, NULL
);
170 EXPECT_FALSE(params
.antialiasing
);
171 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
172 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
173 params
.subpixel_rendering
);
175 query
.pixel_size
= 0;
176 query
.point_size
= 20;
177 params
= GetFontRenderParams(query
, NULL
);
178 EXPECT_TRUE(params
.antialiasing
);
179 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
180 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
181 params
.subpixel_rendering
);
184 TEST_F(FontRenderParamsTest
, Style
) {
185 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
186 // Load a config that disables subpixel rendering for bold text and disables
187 // hinting for italic text.
188 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
189 std::string(kFontconfigFileHeader
) +
190 kFontconfigMatchPatternHeader
+
191 CreateFontconfigEditStanza("antialias", "bool", "true") +
192 CreateFontconfigEditStanza("hinting", "bool", "true") +
193 CreateFontconfigEditStanza("hintstyle", "const", "hintslight") +
194 CreateFontconfigEditStanza("rgba", "const", "rgb") +
195 kFontconfigMatchFooter
+
196 kFontconfigMatchPatternHeader
+
197 CreateFontconfigTestStanza("weight", "eq", "const", "bold") +
198 CreateFontconfigEditStanza("rgba", "const", "none") +
199 kFontconfigMatchFooter
+
200 kFontconfigMatchPatternHeader
+
201 CreateFontconfigTestStanza("slant", "eq", "const", "italic") +
202 CreateFontconfigEditStanza("hinting", "bool", "false") +
203 kFontconfigMatchFooter
+
204 kFontconfigFileFooter
));
206 FontRenderParamsQuery
query(false);
207 query
.style
= Font::NORMAL
;
208 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
209 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
210 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
211 params
.subpixel_rendering
);
213 query
.style
= Font::BOLD
;
214 params
= GetFontRenderParams(query
, NULL
);
215 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
216 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
217 params
.subpixel_rendering
);
219 query
.style
= Font::ITALIC
;
220 params
= GetFontRenderParams(query
, NULL
);
221 EXPECT_EQ(FontRenderParams::HINTING_NONE
, params
.hinting
);
222 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
223 params
.subpixel_rendering
);
225 query
.style
= Font::BOLD
| Font::ITALIC
;
226 params
= GetFontRenderParams(query
, NULL
);
227 EXPECT_EQ(FontRenderParams::HINTING_NONE
, params
.hinting
);
228 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
229 params
.subpixel_rendering
);
232 TEST_F(FontRenderParamsTest
, Scalable
) {
233 // Load a config that only enables antialiasing for scalable fonts.
234 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
235 std::string(kFontconfigFileHeader
) +
236 kFontconfigMatchPatternHeader
+
237 CreateFontconfigEditStanza("antialias", "bool", "false") +
238 kFontconfigMatchFooter
+
239 kFontconfigMatchPatternHeader
+
240 CreateFontconfigTestStanza("scalable", "eq", "bool", "true") +
241 CreateFontconfigEditStanza("antialias", "bool", "true") +
242 kFontconfigMatchFooter
+
243 kFontconfigFileFooter
));
245 // Check that we specifically ask how scalable fonts should be rendered.
246 FontRenderParams params
= GetFontRenderParams(
247 FontRenderParamsQuery(false), NULL
);
248 EXPECT_TRUE(params
.antialiasing
);
251 TEST_F(FontRenderParamsTest
, UseBitmaps
) {
252 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
253 // Load a config that enables embedded bitmaps for fonts <= 10 pixels.
254 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
255 std::string(kFontconfigFileHeader
) +
256 kFontconfigMatchPatternHeader
+
257 CreateFontconfigEditStanza("embeddedbitmap", "bool", "false") +
258 kFontconfigMatchFooter
+
259 kFontconfigMatchPatternHeader
+
260 CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") +
261 CreateFontconfigEditStanza("embeddedbitmap", "bool", "true") +
262 kFontconfigMatchFooter
+
263 kFontconfigFileFooter
));
265 FontRenderParamsQuery
query(false);
266 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
267 EXPECT_FALSE(params
.use_bitmaps
);
269 query
.pixel_size
= 5;
270 params
= GetFontRenderParams(query
, NULL
);
271 EXPECT_TRUE(params
.use_bitmaps
);
274 TEST_F(FontRenderParamsTest
, ForceFullHintingWhenAntialiasingIsDisabled
) {
275 // Load a config that disables antialiasing and hinting while requesting
276 // subpixel rendering.
277 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
278 std::string(kFontconfigFileHeader
) +
279 kFontconfigMatchPatternHeader
+
280 CreateFontconfigEditStanza("antialias", "bool", "false") +
281 CreateFontconfigEditStanza("hinting", "bool", "false") +
282 CreateFontconfigEditStanza("hintstyle", "const", "hintnone") +
283 CreateFontconfigEditStanza("rgba", "const", "rgb") +
284 kFontconfigMatchFooter
+
285 kFontconfigFileFooter
));
287 // Full hinting should be forced. See the comment in GetFontRenderParams() for
289 FontRenderParams params
= GetFontRenderParams(
290 FontRenderParamsQuery(false), NULL
);
291 EXPECT_FALSE(params
.antialiasing
);
292 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
293 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
294 params
.subpixel_rendering
);
295 EXPECT_FALSE(params
.subpixel_positioning
);
298 #if defined(OS_CHROMEOS)
299 TEST_F(FontRenderParamsTest
, ForceSubpixelPositioning
) {
301 FontRenderParams params
=
302 GetFontRenderParams(FontRenderParamsQuery(false), NULL
);
303 EXPECT_TRUE(params
.antialiasing
);
304 EXPECT_FALSE(params
.subpixel_positioning
);
305 SetFontRenderParamsDeviceScaleFactor(1.0f
);
307 ClearFontRenderParamsCacheForTest();
308 SetFontRenderParamsDeviceScaleFactor(1.25f
);
309 // Subpixel positioning should be forced.
311 FontRenderParams params
=
312 GetFontRenderParams(FontRenderParamsQuery(false), NULL
);
313 EXPECT_TRUE(params
.antialiasing
);
314 EXPECT_TRUE(params
.subpixel_positioning
);
315 SetFontRenderParamsDeviceScaleFactor(1.0f
);
320 TEST_F(FontRenderParamsTest
, OnlySetConfiguredValues
) {
321 // Configure the LinuxFontDelegate (which queries GtkSettings on desktop
322 // Linux) to request subpixel rendering.
323 FontRenderParams system_params
;
324 system_params
.subpixel_rendering
= FontRenderParams::SUBPIXEL_RENDERING_RGB
;
325 test_font_delegate_
.set_params(system_params
);
327 // Load a Fontconfig config that enables antialiasing but doesn't say anything
328 // about subpixel rendering.
329 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
330 std::string(kFontconfigFileHeader
) +
331 kFontconfigMatchPatternHeader
+
332 CreateFontconfigEditStanza("antialias", "bool", "true") +
333 kFontconfigMatchFooter
+
334 kFontconfigFileFooter
));
336 // The subpixel rendering setting from the delegate should make it through.
337 FontRenderParams params
= GetFontRenderParams(
338 FontRenderParamsQuery(false), NULL
);
339 EXPECT_EQ(system_params
.subpixel_rendering
, params
.subpixel_rendering
);
342 TEST_F(FontRenderParamsTest
, NoFontconfigMatch
) {
343 // Don't load a Fontconfig configuration.
344 FontRenderParams system_params
;
345 system_params
.antialiasing
= true;
346 system_params
.hinting
= FontRenderParams::HINTING_MEDIUM
;
347 system_params
.subpixel_rendering
= FontRenderParams::SUBPIXEL_RENDERING_RGB
;
348 test_font_delegate_
.set_params(system_params
);
350 FontRenderParamsQuery
query(false);
351 query
.families
.push_back("Arial");
352 query
.families
.push_back("Times New Roman");
353 query
.pixel_size
= 10;
354 std::string suggested_family
;
355 FontRenderParams params
= GetFontRenderParams(query
, &suggested_family
);
357 // The system params and the first requested family should be returned.
358 EXPECT_EQ(system_params
.antialiasing
, params
.antialiasing
);
359 EXPECT_EQ(system_params
.hinting
, params
.hinting
);
360 EXPECT_EQ(system_params
.subpixel_rendering
, params
.subpixel_rendering
);
361 EXPECT_EQ(query
.families
[0], suggested_family
);
364 TEST_F(FontRenderParamsTest
, MissingFamily
) {
365 // With Arial and Verdana installed, request (in order) Helvetica, Arial, and
366 // Verdana and check that Arial is returned.
367 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
368 ASSERT_TRUE(LoadSystemFont("verdana.ttf"));
369 FontRenderParamsQuery
query(false);
370 query
.families
.push_back("Helvetica");
371 query
.families
.push_back("Arial");
372 query
.families
.push_back("Verdana");
373 std::string suggested_family
;
374 GetFontRenderParams(query
, &suggested_family
);
375 EXPECT_EQ("Arial", suggested_family
);
378 TEST_F(FontRenderParamsTest
, SubstituteFamily
) {
379 // Configure Fontconfig to use Verdana for both Helvetica and Arial.
380 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
381 ASSERT_TRUE(LoadSystemFont("verdana.ttf"));
382 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
383 std::string(kFontconfigFileHeader
) +
384 CreateFontconfigAliasStanza("Helvetica", "Verdana") +
385 kFontconfigMatchPatternHeader
+
386 CreateFontconfigTestStanza("family", "eq", "string", "Arial") +
387 CreateFontconfigEditStanza("family", "string", "Verdana") +
388 kFontconfigMatchFooter
+
389 kFontconfigFileFooter
));
391 FontRenderParamsQuery
query(false);
392 query
.families
.push_back("Helvetica");
393 std::string suggested_family
;
394 GetFontRenderParams(query
, &suggested_family
);
395 EXPECT_EQ("Verdana", suggested_family
);
397 query
.families
.clear();
398 query
.families
.push_back("Arial");
399 suggested_family
.clear();
400 GetFontRenderParams(query
, &suggested_family
);
401 EXPECT_EQ("Verdana", suggested_family
);