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 kFontconfigFileFooter
));
114 FontRenderParams params
= GetFontRenderParams(
115 FontRenderParamsQuery(true), NULL
);
116 EXPECT_TRUE(params
.antialiasing
);
117 EXPECT_TRUE(params
.autohinter
);
118 EXPECT_TRUE(params
.use_bitmaps
);
119 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
120 EXPECT_FALSE(params
.subpixel_positioning
);
121 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
122 params
.subpixel_rendering
);
125 TEST_F(FontRenderParamsTest
, Size
) {
126 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
127 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
128 std::string(kFontconfigFileHeader
) +
129 kFontconfigMatchPatternHeader
+
130 CreateFontconfigEditStanza("antialias", "bool", "true") +
131 CreateFontconfigEditStanza("hinting", "bool", "true") +
132 CreateFontconfigEditStanza("hintstyle", "const", "hintfull") +
133 CreateFontconfigEditStanza("rgba", "const", "none") +
134 kFontconfigMatchFooter
+
135 kFontconfigMatchPatternHeader
+
136 CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") +
137 CreateFontconfigEditStanza("antialias", "bool", "false") +
138 kFontconfigMatchFooter
+
139 kFontconfigMatchPatternHeader
+
140 CreateFontconfigTestStanza("size", "more_eq", "double", "20") +
141 CreateFontconfigEditStanza("hintstyle", "const", "hintslight") +
142 CreateFontconfigEditStanza("rgba", "const", "rgb") +
143 kFontconfigMatchFooter
+
144 kFontconfigFileFooter
));
146 // The defaults should be used when the supplied size isn't matched by the
147 // second or third blocks.
148 FontRenderParamsQuery
query(false);
149 query
.pixel_size
= 12;
150 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
151 EXPECT_TRUE(params
.antialiasing
);
152 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
153 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
154 params
.subpixel_rendering
);
156 query
.pixel_size
= 10;
157 params
= GetFontRenderParams(query
, NULL
);
158 EXPECT_FALSE(params
.antialiasing
);
159 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
160 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
161 params
.subpixel_rendering
);
163 query
.pixel_size
= 0;
164 query
.point_size
= 20;
165 params
= GetFontRenderParams(query
, NULL
);
166 EXPECT_TRUE(params
.antialiasing
);
167 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
168 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
169 params
.subpixel_rendering
);
172 TEST_F(FontRenderParamsTest
, Style
) {
173 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
174 // Load a config that disables subpixel rendering for bold text and disables
175 // hinting for italic text.
176 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
177 std::string(kFontconfigFileHeader
) +
178 kFontconfigMatchPatternHeader
+
179 CreateFontconfigEditStanza("antialias", "bool", "true") +
180 CreateFontconfigEditStanza("hinting", "bool", "true") +
181 CreateFontconfigEditStanza("hintstyle", "const", "hintslight") +
182 CreateFontconfigEditStanza("rgba", "const", "rgb") +
183 kFontconfigMatchFooter
+
184 kFontconfigMatchPatternHeader
+
185 CreateFontconfigTestStanza("weight", "eq", "const", "bold") +
186 CreateFontconfigEditStanza("rgba", "const", "none") +
187 kFontconfigMatchFooter
+
188 kFontconfigMatchPatternHeader
+
189 CreateFontconfigTestStanza("slant", "eq", "const", "italic") +
190 CreateFontconfigEditStanza("hinting", "bool", "false") +
191 kFontconfigMatchFooter
+
192 kFontconfigFileFooter
));
194 FontRenderParamsQuery
query(false);
195 query
.style
= Font::NORMAL
;
196 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
197 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
198 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
199 params
.subpixel_rendering
);
201 query
.style
= Font::BOLD
;
202 params
= GetFontRenderParams(query
, NULL
);
203 EXPECT_EQ(FontRenderParams::HINTING_SLIGHT
, params
.hinting
);
204 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
205 params
.subpixel_rendering
);
207 query
.style
= Font::ITALIC
;
208 params
= GetFontRenderParams(query
, NULL
);
209 EXPECT_EQ(FontRenderParams::HINTING_NONE
, params
.hinting
);
210 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB
,
211 params
.subpixel_rendering
);
213 query
.style
= Font::BOLD
| Font::ITALIC
;
214 params
= GetFontRenderParams(query
, NULL
);
215 EXPECT_EQ(FontRenderParams::HINTING_NONE
, params
.hinting
);
216 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
217 params
.subpixel_rendering
);
220 TEST_F(FontRenderParamsTest
, Scalable
) {
221 // Load a config that only enables antialiasing for scalable fonts.
222 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
223 std::string(kFontconfigFileHeader
) +
224 kFontconfigMatchPatternHeader
+
225 CreateFontconfigEditStanza("antialias", "bool", "false") +
226 kFontconfigMatchFooter
+
227 kFontconfigMatchPatternHeader
+
228 CreateFontconfigTestStanza("scalable", "eq", "bool", "true") +
229 CreateFontconfigEditStanza("antialias", "bool", "true") +
230 kFontconfigMatchFooter
+
231 kFontconfigFileFooter
));
233 // Check that we specifically ask how scalable fonts should be rendered.
234 FontRenderParams params
= GetFontRenderParams(
235 FontRenderParamsQuery(false), NULL
);
236 EXPECT_TRUE(params
.antialiasing
);
239 TEST_F(FontRenderParamsTest
, UseBitmaps
) {
240 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
241 // Load a config that enables embedded bitmaps for fonts <= 10 pixels.
242 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
243 std::string(kFontconfigFileHeader
) +
244 kFontconfigMatchPatternHeader
+
245 CreateFontconfigEditStanza("embeddedbitmap", "bool", "false") +
246 kFontconfigMatchFooter
+
247 kFontconfigMatchPatternHeader
+
248 CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") +
249 CreateFontconfigEditStanza("embeddedbitmap", "bool", "true") +
250 kFontconfigMatchFooter
+
251 kFontconfigFileFooter
));
253 FontRenderParamsQuery
query(false);
254 FontRenderParams params
= GetFontRenderParams(query
, NULL
);
255 EXPECT_FALSE(params
.use_bitmaps
);
257 query
.pixel_size
= 5;
258 params
= GetFontRenderParams(query
, NULL
);
259 EXPECT_TRUE(params
.use_bitmaps
);
262 TEST_F(FontRenderParamsTest
, ForceFullHintingWhenAntialiasingIsDisabled
) {
263 // Load a config that disables antialiasing and hinting while requesting
264 // subpixel rendering.
265 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
266 std::string(kFontconfigFileHeader
) +
267 kFontconfigMatchPatternHeader
+
268 CreateFontconfigEditStanza("antialias", "bool", "false") +
269 CreateFontconfigEditStanza("hinting", "bool", "false") +
270 CreateFontconfigEditStanza("hintstyle", "const", "hintnone") +
271 CreateFontconfigEditStanza("rgba", "const", "rgb") +
272 kFontconfigMatchFooter
+
273 kFontconfigFileFooter
));
275 // Full hinting should be forced. See the comment in GetFontRenderParams() for
277 FontRenderParams params
= GetFontRenderParams(
278 FontRenderParamsQuery(false), NULL
);
279 EXPECT_FALSE(params
.antialiasing
);
280 EXPECT_EQ(FontRenderParams::HINTING_FULL
, params
.hinting
);
281 EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE
,
282 params
.subpixel_rendering
);
283 EXPECT_FALSE(params
.subpixel_positioning
);
286 #if defined(OS_CHROMEOS)
287 TEST_F(FontRenderParamsTest
, ForceSubpixelPositioning
) {
289 FontRenderParams params
=
290 GetFontRenderParams(FontRenderParamsQuery(false), NULL
);
291 EXPECT_TRUE(params
.antialiasing
);
292 EXPECT_FALSE(params
.subpixel_positioning
);
293 SetFontRenderParamsDeviceScaleFactor(1.0f
);
295 ClearFontRenderParamsCacheForTest();
296 SetFontRenderParamsDeviceScaleFactor(1.25f
);
297 // Subpixel positioning should be forced.
299 FontRenderParams params
=
300 GetFontRenderParams(FontRenderParamsQuery(false), NULL
);
301 EXPECT_TRUE(params
.antialiasing
);
302 EXPECT_TRUE(params
.subpixel_positioning
);
303 SetFontRenderParamsDeviceScaleFactor(1.0f
);
308 TEST_F(FontRenderParamsTest
, OnlySetConfiguredValues
) {
309 // Configure the LinuxFontDelegate (which queries GtkSettings on desktop
310 // Linux) to request subpixel rendering.
311 FontRenderParams system_params
;
312 system_params
.subpixel_rendering
= FontRenderParams::SUBPIXEL_RENDERING_RGB
;
313 test_font_delegate_
.set_params(system_params
);
315 // Load a Fontconfig config that enables antialiasing but doesn't say anything
316 // about subpixel rendering.
317 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
318 std::string(kFontconfigFileHeader
) +
319 kFontconfigMatchPatternHeader
+
320 CreateFontconfigEditStanza("antialias", "bool", "true") +
321 kFontconfigMatchFooter
+
322 kFontconfigFileFooter
));
324 // The subpixel rendering setting from the delegate should make it through.
325 FontRenderParams params
= GetFontRenderParams(
326 FontRenderParamsQuery(false), NULL
);
327 EXPECT_EQ(system_params
.subpixel_rendering
, params
.subpixel_rendering
);
330 TEST_F(FontRenderParamsTest
, NoFontconfigMatch
) {
331 // Don't load a Fontconfig configuration.
332 FontRenderParams system_params
;
333 system_params
.antialiasing
= true;
334 system_params
.hinting
= FontRenderParams::HINTING_MEDIUM
;
335 system_params
.subpixel_rendering
= FontRenderParams::SUBPIXEL_RENDERING_RGB
;
336 test_font_delegate_
.set_params(system_params
);
338 FontRenderParamsQuery
query(false);
339 query
.families
.push_back("Arial");
340 query
.families
.push_back("Times New Roman");
341 query
.pixel_size
= 10;
342 std::string suggested_family
;
343 FontRenderParams params
= GetFontRenderParams(query
, &suggested_family
);
345 // The system params and the first requested family should be returned.
346 EXPECT_EQ(system_params
.antialiasing
, params
.antialiasing
);
347 EXPECT_EQ(system_params
.hinting
, params
.hinting
);
348 EXPECT_EQ(system_params
.subpixel_rendering
, params
.subpixel_rendering
);
349 EXPECT_EQ(query
.families
[0], suggested_family
);
352 TEST_F(FontRenderParamsTest
, MissingFamily
) {
353 // With Arial and Verdana installed, request (in order) Helvetica, Arial, and
354 // Verdana and check that Arial is returned.
355 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
356 ASSERT_TRUE(LoadSystemFont("verdana.ttf"));
357 FontRenderParamsQuery
query(false);
358 query
.families
.push_back("Helvetica");
359 query
.families
.push_back("Arial");
360 query
.families
.push_back("Verdana");
361 std::string suggested_family
;
362 GetFontRenderParams(query
, &suggested_family
);
363 EXPECT_EQ("Arial", suggested_family
);
366 TEST_F(FontRenderParamsTest
, SubstituteFamily
) {
367 // Configure Fontconfig to use Verdana for both Helvetica and Arial.
368 ASSERT_TRUE(LoadSystemFont("arial.ttf"));
369 ASSERT_TRUE(LoadSystemFont("verdana.ttf"));
370 ASSERT_TRUE(LoadConfigDataIntoFontconfig(temp_dir_
.path(),
371 std::string(kFontconfigFileHeader
) +
372 CreateFontconfigAliasStanza("Helvetica", "Verdana") +
373 kFontconfigMatchPatternHeader
+
374 CreateFontconfigTestStanza("family", "eq", "string", "Arial") +
375 CreateFontconfigEditStanza("family", "string", "Verdana") +
376 kFontconfigMatchFooter
+
377 kFontconfigFileFooter
));
379 FontRenderParamsQuery
query(false);
380 query
.families
.push_back("Helvetica");
381 std::string suggested_family
;
382 GetFontRenderParams(query
, &suggested_family
);
383 EXPECT_EQ("Verdana", suggested_family
);
385 query
.families
.clear();
386 query
.families
.push_back("Arial");
387 suggested_family
.clear();
388 GetFontRenderParams(query
, &suggested_family
);
389 EXPECT_EQ("Verdana", suggested_family
);