OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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 "content/common/font_warmup_win.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/files/file_path.h" | |
10 #include "base/logging.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/sys_byteorder.h" | |
13 #include "base/win/windows_version.h" | |
14 #include "skia/ext/refptr.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 #include "third_party/skia/include/core/SkString.h" | |
17 #include "third_party/skia/include/core/SkTypeface.h" | |
18 #include "third_party/skia/include/ports/SkFontMgr.h" | |
19 | |
20 namespace content { | |
21 | |
22 namespace { | |
23 | |
24 class TestSkTypeface : public SkTypeface { | |
25 public: | |
26 TestSkTypeface(const SkFontStyle& style, | |
27 const char* familyName, | |
28 SkFontTableTag tag, | |
29 const char* data, | |
30 size_t dataLength) | |
31 : SkTypeface(style, 0), | |
32 familyName_(familyName), | |
33 tag_(tag), | |
34 data_(data, data + dataLength) {} | |
35 | |
36 protected: | |
37 SkScalerContext* onCreateScalerContext(const SkDescriptor*) const override { | |
38 ADD_FAILURE(); | |
39 return nullptr; | |
40 } | |
41 void onFilterRec(SkScalerContextRec*) const override { ADD_FAILURE(); } | |
42 SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( | |
43 PerGlyphInfo, | |
44 const uint32_t* glyphIDs, | |
45 uint32_t glyphIDsCount) const override { | |
46 ADD_FAILURE(); | |
47 return nullptr; | |
48 } | |
49 | |
50 SkStreamAsset* onOpenStream(int* ttcIndex) const override { | |
51 ADD_FAILURE(); | |
52 return nullptr; | |
53 } | |
54 | |
55 SkFontData* onCreateFontData() const override { | |
56 ADD_FAILURE(); | |
57 return nullptr; | |
58 } | |
59 | |
60 void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const override { | |
61 ADD_FAILURE(); | |
62 } | |
63 | |
64 int onCharsToGlyphs(const void* chars, | |
65 Encoding, | |
66 uint16_t glyphs[], | |
67 int glyphCount) const override { | |
68 ADD_FAILURE(); | |
69 return 0; | |
70 } | |
71 | |
72 int onCountGlyphs() const override { | |
73 ADD_FAILURE(); | |
74 return 0; | |
75 } | |
76 | |
77 int onGetUPEM() const override { | |
78 ADD_FAILURE(); | |
79 return 0; | |
80 } | |
81 bool onGetKerningPairAdjustments(const uint16_t glyphs[], | |
82 int count, | |
83 int32_t adjustments[]) const override { | |
84 ADD_FAILURE(); | |
85 return false; | |
86 } | |
87 | |
88 void onGetFamilyName(SkString* familyName) const override { | |
89 *familyName = familyName_; | |
90 } | |
91 | |
92 LocalizedStrings* onCreateFamilyNameIterator() const override { | |
93 ADD_FAILURE(); | |
94 return nullptr; | |
95 } | |
96 | |
97 int onGetTableTags(SkFontTableTag tags[]) const override { | |
98 ADD_FAILURE(); | |
99 return 0; | |
100 } | |
101 | |
102 size_t onGetTableData(SkFontTableTag tag, | |
103 size_t offset, | |
104 size_t length, | |
105 void* data) const override { | |
106 size_t retsize = 0; | |
107 if (tag == tag_) { | |
108 retsize = length > data_.size() ? data_.size() : length; | |
109 if (data) | |
110 memcpy(data, &data_[0], retsize); | |
111 } | |
112 return retsize; | |
113 } | |
114 | |
115 bool onComputeBounds(SkRect*) const override { | |
116 ADD_FAILURE(); | |
117 return false; | |
118 } | |
119 | |
120 private: | |
121 SkString familyName_; | |
122 SkFontTableTag tag_; | |
123 std::vector<char> data_; | |
124 }; | |
125 | |
126 const char* kTestFontFamily = "GDITest"; | |
127 const wchar_t* kTestFontFamilyW = L"GDITest"; | |
128 const SkFontTableTag kTestFontTableTag = 0x11223344; | |
129 const char* kTestFontData = "GDITestGDITest"; | |
130 const wchar_t* kTestFontFamilyInvalid = L"InvalidFont"; | |
131 | |
132 class TestSkFontMgr : public SkFontMgr { | |
133 public: | |
134 TestSkFontMgr() { content::SetPreSandboxWarmupFontMgr(this); } | |
135 ~TestSkFontMgr() { content::SetPreSandboxWarmupFontMgr(nullptr); } | |
136 | |
137 protected: | |
138 // Implement the virtual methods | |
139 int onCountFamilies() const override { return 1; } | |
140 | |
141 void onGetFamilyName(int index, SkString* familyName) const override { | |
142 if (index == 0) | |
143 *familyName = kTestFontFamily; | |
144 } | |
145 | |
146 SkFontStyleSet* onCreateStyleSet(int index) const override { | |
147 ADD_FAILURE(); | |
148 return nullptr; | |
149 } | |
150 | |
151 /** May return nullptr if the name is not found. */ | |
nasko
2015/09/21 15:58:20
Use // for comments.
forshaw
2015/09/21 22:06:20
Acknowledged.
| |
152 SkFontStyleSet* onMatchFamily(const char familyName[]) const override { | |
153 ADD_FAILURE(); | |
154 return nullptr; | |
155 } | |
156 | |
157 SkTypeface* onMatchFamilyStyle(const char familyName[], | |
158 const SkFontStyle&) const override { | |
159 if (strcmp(familyName, kTestFontFamily) == 0) { | |
nasko
2015/09/21 15:58:20
nit: no need for {} in one line if statements.
forshaw
2015/09/21 22:06:20
Acknowledged.
| |
160 return createTypeface(); | |
161 } | |
162 return nullptr; | |
163 } | |
164 | |
165 SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], | |
166 const SkFontStyle&, | |
167 const char* bcp47[], | |
168 int bcp47Count, | |
169 SkUnichar character) const override { | |
170 ADD_FAILURE(); | |
171 return nullptr; | |
172 } | |
173 | |
174 SkTypeface* onMatchFaceStyle(const SkTypeface*, | |
175 const SkFontStyle&) const override { | |
176 ADD_FAILURE(); | |
177 return nullptr; | |
178 } | |
179 | |
180 SkTypeface* onCreateFromData(SkData*, int ttcIndex) const override { | |
181 ADD_FAILURE(); | |
182 return nullptr; | |
183 } | |
184 | |
185 SkTypeface* onCreateFromStream(SkStreamAsset*, int ttcIndex) const override { | |
186 ADD_FAILURE(); | |
187 return nullptr; | |
188 } | |
189 | |
190 SkTypeface* onCreateFromFontData(SkFontData*) const override { | |
191 ADD_FAILURE(); | |
192 return nullptr; | |
193 } | |
194 | |
195 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { | |
196 ADD_FAILURE(); | |
197 return nullptr; | |
198 } | |
199 | |
200 SkTypeface* onLegacyCreateTypeface(const char familyName[], | |
201 unsigned styleBits) const override { | |
202 ADD_FAILURE(); | |
203 return nullptr; | |
204 } | |
205 | |
206 private: | |
207 SkTypeface* createTypeface() const { | |
208 SkFontStyle style(400, 100, SkFontStyle::kUpright_Slant); | |
209 | |
210 return new TestSkTypeface(style, kTestFontFamily, | |
211 base::ByteSwap(kTestFontTableTag), kTestFontData, | |
212 strlen(kTestFontData)); | |
213 } | |
214 }; | |
215 | |
216 void InitLogFont(LOGFONTW* logfont, const wchar_t* fontname) { | |
217 size_t length = std::min(sizeof(logfont->lfFaceName), | |
218 (wcslen(fontname) + 1) * sizeof(wchar_t)); | |
219 memcpy(logfont->lfFaceName, fontname, length); | |
220 } | |
221 | |
222 content::GdiFontPatchData* SetupTest() { | |
223 HMODULE module_handle; | |
224 if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, | |
225 reinterpret_cast<LPCWSTR>(SetupTest), | |
226 &module_handle)) { | |
227 WCHAR module_path[MAX_PATH]; | |
228 | |
229 if (GetModuleFileNameW(module_handle, module_path, MAX_PATH) > 0) { | |
230 base::FilePath path(module_path); | |
231 content::ResetEmulatedGdiHandles(); | |
232 return content::PatchGdiFontEnumeration(path); | |
233 } | |
234 } | |
235 return nullptr; | |
236 } | |
237 | |
238 int CALLBACK EnumFontCallbackTest(const LOGFONT* log_font, | |
239 const TEXTMETRIC* text_metric, | |
240 DWORD font_type, | |
241 LPARAM param) { | |
242 const NEWTEXTMETRICEX* new_text_metric = | |
243 reinterpret_cast<const NEWTEXTMETRICEX*>(text_metric); | |
244 | |
245 return !(font_type & TRUETYPE_FONTTYPE) && | |
246 !(new_text_metric->ntmTm.ntmFlags & NTM_PS_OPENTYPE); | |
247 } | |
248 | |
249 } // namespace | |
250 | |
251 TEST(GDIFontEmulationTest, CreateDeleteDCSuccess) { | |
252 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
253 return; | |
254 TestSkFontMgr fontmgr; | |
255 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
256 EXPECT_FALSE(!patch_data); | |
257 | |
258 HDC hdc = CreateCompatibleDC(0); | |
259 EXPECT_NE(hdc, nullptr); | |
260 EXPECT_EQ(GetEmulatedGdiHandleCount(), 1); | |
261 EXPECT_TRUE(DeleteDC(hdc)); | |
262 EXPECT_EQ(GetEmulatedGdiHandleCount(), 0); | |
263 } | |
264 | |
265 TEST(GDIFontEmulationTest, CreateUniqueDCSuccess) { | |
266 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
267 return; | |
268 TestSkFontMgr fontmgr; | |
269 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
270 EXPECT_NE(patch_data, nullptr); | |
271 | |
272 HDC hdc1 = CreateCompatibleDC(0); | |
273 EXPECT_NE(hdc1, nullptr); | |
274 HDC hdc2 = CreateCompatibleDC(0); | |
275 EXPECT_NE(hdc2, nullptr); | |
276 EXPECT_NE(hdc1, hdc2); | |
277 EXPECT_TRUE(DeleteDC(hdc2)); | |
278 EXPECT_EQ(GetEmulatedGdiHandleCount(), 1); | |
279 EXPECT_TRUE(DeleteDC(hdc1)); | |
280 EXPECT_EQ(GetEmulatedGdiHandleCount(), 0); | |
281 } | |
282 | |
283 TEST(GDIFontEmulationTest, CreateFontSuccess) { | |
284 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
285 return; | |
286 TestSkFontMgr fontmgr; | |
287 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
288 EXPECT_NE(patch_data, nullptr); | |
289 LOGFONTW logfont = {0}; | |
290 InitLogFont(&logfont, kTestFontFamilyW); | |
291 HFONT font = CreateFontIndirectW(&logfont); | |
292 EXPECT_NE(font, nullptr); | |
293 EXPECT_TRUE(DeleteObject(font)); | |
294 EXPECT_EQ(GetEmulatedGdiHandleCount(), 0); | |
295 } | |
296 | |
297 TEST(GDIFontEmulationTest, CreateFontFailure) { | |
298 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
299 return; | |
300 TestSkFontMgr fontmgr; | |
301 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
302 EXPECT_NE(patch_data, nullptr); | |
303 LOGFONTW logfont = {0}; | |
304 InitLogFont(&logfont, kTestFontFamilyInvalid); | |
305 HFONT font = CreateFontIndirectW(&logfont); | |
306 EXPECT_EQ(font, nullptr); | |
307 } | |
308 | |
309 TEST(GDIFontEmulationTest, EnumFontFamilySuccess) { | |
310 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
311 return; | |
312 TestSkFontMgr fontmgr; | |
313 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
314 EXPECT_NE(patch_data, nullptr); | |
315 HDC hdc = CreateCompatibleDC(0); | |
316 EXPECT_NE(hdc, nullptr); | |
317 LOGFONTW logfont = {0}; | |
318 InitLogFont(&logfont, kTestFontFamilyW); | |
319 int res = EnumFontFamiliesExW(hdc, &logfont, EnumFontCallbackTest, 0, 0); | |
320 EXPECT_FALSE(res); | |
321 EXPECT_TRUE(DeleteDC(hdc)); | |
322 } | |
323 | |
324 TEST(GDIFontEmulationTest, EnumFontFamilyFailure) { | |
325 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
326 return; | |
327 TestSkFontMgr fontmgr; | |
328 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
329 EXPECT_NE(patch_data, nullptr); | |
330 HDC hdc = CreateCompatibleDC(0); | |
331 EXPECT_NE(hdc, nullptr); | |
332 LOGFONTW logfont = {0}; | |
333 InitLogFont(&logfont, kTestFontFamilyInvalid); | |
334 int res = EnumFontFamiliesExW(hdc, &logfont, EnumFontCallbackTest, 0, 0); | |
335 EXPECT_TRUE(res); | |
336 EXPECT_TRUE(DeleteDC(hdc)); | |
337 } | |
338 | |
339 TEST(GDIFontEmulationTest, DeleteDCFailure) { | |
340 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
341 return; | |
342 TestSkFontMgr fontmgr; | |
343 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
344 EXPECT_NE(patch_data, nullptr); | |
345 HDC hdc = reinterpret_cast<HDC>(0x55667788); | |
346 EXPECT_FALSE(DeleteDC(hdc)); | |
347 } | |
348 | |
349 TEST(GDIFontEmulationTest, DeleteObjectFailure) { | |
350 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
351 return; | |
352 TestSkFontMgr fontmgr; | |
353 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
354 EXPECT_NE(patch_data, nullptr); | |
355 HFONT font = reinterpret_cast<HFONT>(0x88aabbcc); | |
356 EXPECT_FALSE(DeleteObject(font)); | |
357 } | |
358 | |
359 TEST(GDIFontEmulationTest, GetFontDataSizeSuccess) { | |
360 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
361 return; | |
362 TestSkFontMgr fontmgr; | |
363 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
364 EXPECT_NE(patch_data, nullptr); | |
365 HDC hdc = CreateCompatibleDC(0); | |
366 EXPECT_NE(hdc, nullptr); | |
367 LOGFONTW logfont = {0}; | |
368 InitLogFont(&logfont, kTestFontFamilyW); | |
369 HFONT font = CreateFontIndirectW(&logfont); | |
370 EXPECT_NE(font, nullptr); | |
371 EXPECT_EQ(SelectObject(hdc, font), nullptr); | |
372 DWORD size = GetFontData(hdc, kTestFontTableTag, 0, nullptr, 0); | |
373 DWORD data_size = static_cast<DWORD>(strlen(kTestFontData)); | |
374 EXPECT_EQ(size, data_size); | |
375 EXPECT_TRUE(DeleteObject(font)); | |
376 EXPECT_TRUE(DeleteDC(hdc)); | |
377 } | |
378 | |
379 TEST(GDIFontEmulationTest, GetFontDataInvalidTagSuccess) { | |
380 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
381 return; | |
382 TestSkFontMgr fontmgr; | |
383 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
384 EXPECT_NE(patch_data, nullptr); | |
385 HDC hdc = CreateCompatibleDC(0); | |
386 EXPECT_NE(hdc, nullptr); | |
387 LOGFONTW logfont = {0}; | |
388 InitLogFont(&logfont, kTestFontFamilyW); | |
389 HFONT font = CreateFontIndirectW(&logfont); | |
390 EXPECT_NE(font, nullptr); | |
391 EXPECT_EQ(SelectObject(hdc, font), nullptr); | |
392 DWORD size = GetFontData(hdc, kTestFontTableTag + 1, 0, nullptr, 0); | |
393 EXPECT_EQ(size, GDI_ERROR); | |
394 EXPECT_TRUE(DeleteObject(font)); | |
395 EXPECT_TRUE(DeleteDC(hdc)); | |
396 } | |
397 | |
398 TEST(GDIFontEmulationTest, GetFontDataInvalidFontSuccess) { | |
399 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
400 return; | |
401 TestSkFontMgr fontmgr; | |
402 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
403 EXPECT_NE(patch_data, nullptr); | |
404 HDC hdc = CreateCompatibleDC(0); | |
405 EXPECT_NE(hdc, nullptr); | |
406 DWORD size = GetFontData(hdc, kTestFontTableTag, 0, nullptr, 0); | |
407 EXPECT_EQ(size, GDI_ERROR); | |
408 EXPECT_TRUE(DeleteDC(hdc)); | |
409 } | |
410 | |
411 TEST(GDIFontEmulationTest, GetFontDataDataSuccess) { | |
412 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
413 return; | |
414 TestSkFontMgr fontmgr; | |
415 scoped_ptr<GdiFontPatchData> patch_data(SetupTest()); | |
416 EXPECT_NE(patch_data, nullptr); | |
417 HDC hdc = CreateCompatibleDC(0); | |
418 EXPECT_NE(hdc, nullptr); | |
419 LOGFONTW logfont = {0}; | |
420 InitLogFont(&logfont, kTestFontFamilyW); | |
421 HFONT font = CreateFontIndirectW(&logfont); | |
422 EXPECT_NE(font, nullptr); | |
423 EXPECT_EQ(SelectObject(hdc, font), nullptr); | |
424 DWORD data_size = static_cast<DWORD>(strlen(kTestFontData)); | |
425 std::vector<char> data(data_size); | |
426 DWORD size = GetFontData(hdc, kTestFontTableTag, 0, &data[0], data.size()); | |
427 EXPECT_EQ(size, data_size); | |
428 EXPECT_EQ(memcmp(&data[0], kTestFontData, data.size()), 0); | |
429 EXPECT_TRUE(DeleteObject(font)); | |
430 EXPECT_TRUE(DeleteDC(hdc)); | |
431 } | |
432 | |
433 } // namespace content | |
OLD | NEW |