• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkCommandLineFlags.h"
9 #include "SkFontMgr.h"
10 #include "SkOTTable_name.h"
11 #include "SkTypeface.h"
12 #include "Test.h"
13 
14 #include <stddef.h>
15 
16 template <size_t R, size_t D> struct Format0NameTable {
17     SkOTTableName header;
18     SkOTTableName::Record nameRecord[R];
19     char data[D];
20 };
21 
22 template <size_t R, size_t L, size_t D> struct Format1NameTable {
23     SkOTTableName header;
24     SkOTTableName::Record nameRecord[R];
25     struct {
26         SkOTTableName::Format1Ext header;
27         SkOTTableName::Format1Ext::LangTagRecord langTagRecord[L];
28     } format1ext;
29     char data[D];
30 };
31 
32 typedef Format0NameTable<1, 9> SimpleFormat0NameTable;
33 SimpleFormat0NameTable simpleFormat0NameTable = {
34     /*header*/ {
35         /*format*/ SkOTTableName::format_0,
36         /*count*/ SkTEndianSwap16<1>::value,
37         /*stringOffset*/ SkTEndianSwap16<offsetof(SimpleFormat0NameTable, data)>::value,
38     },
39     /*nameRecord[]*/ {
40         /*Record*/ {
41             /*platformID*/ { SkOTTableName::Record::PlatformID::Windows },
42             /*encodingID*/ { SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2 },
43             /*languageID*/ { SkOTTableName::Record::LanguageID::Windows::English_UnitedStates },
44             /*nameID*/ { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
45             /*length*/ SkTEndianSwap16<8>::value,
46             /*offset*/ SkTEndianSwap16<0>::value,
47         }
48     },
49     /*data*/ "\x0" "T" "\x0" "e" "\x0" "s" "\x0" "t",
50 };
51 
52 typedef Format1NameTable<1, 1, 19> SimpleFormat1NameTable;
53 SimpleFormat1NameTable simpleFormat1NameTable = {
54     /*header*/ {
55         /*format*/ SkOTTableName::format_1,
56         /*count*/ SkTEndianSwap16<1>::value,
57         /*stringOffset*/ SkTEndianSwap16<offsetof(SimpleFormat1NameTable, data)>::value,
58     },
59     /*nameRecord[]*/ {
60         /*Record*/ {
61             /*platformID*/ { SkOTTableName::Record::PlatformID::Windows },
62             /*encodingID*/ { SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2 },
63             /*languageID*/ { SkTEndianSwap16<0x8000 + 0>::value },
64             /*nameID*/ { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
65             /*length*/ SkTEndianSwap16<8>::value,
66             /*offset*/ SkTEndianSwap16<0>::value,
67         }
68     },
69     /*format1ext*/ {
70         /*header*/ {
71             /*langTagCount*/ SkTEndianSwap16<1>::value,
72         },
73         /*langTagRecord[]*/ {
74             /*LangTagRecord*/ {
75                 /*length*/ SkTEndianSwap16<10>::value,
76                 /*offset*/ SkTEndianSwap16<8>::value,
77             },
78         },
79     },
80     /*data*/ "\x0" "T" "\x0" "e" "\x0" "s" "\x0" "t"
81              "\x0" "e" "\x0" "n" "\x0" "-" "\x0" "U" "\x0" "S",
82 };
83 
84 struct FontNamesTest {
85     SkOTTableName* data;
86     SkOTTableName::Record::NameID nameID;
87     size_t nameCount;
88     struct {
89         const char* name;
90         const char* language;
91     } names[10];
92 
93 } test[] = {
94     {
95         (SkOTTableName*)&simpleFormat0NameTable,
96         { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
97         1,
98         {
99             { "Test", "en-US" },
100         },
101     },
102     {
103         (SkOTTableName*)&simpleFormat1NameTable,
104         { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
105         1,
106         {
107             { "Test", "en-US" },
108         },
109     },
110 };
111 
test_synthetic(skiatest::Reporter * reporter,bool verbose)112 static void test_synthetic(skiatest::Reporter* reporter, bool verbose) {
113     for (size_t i = 0; i < SK_ARRAY_COUNT(test); ++i) {
114         SkOTTableName::Iterator iter(*test[i].data, test[i].nameID.predefined.value);
115         SkOTTableName::Iterator::Record record;
116         size_t nameIndex = 0;
117         while (nameIndex < test[i].nameCount && iter.next(record)) {
118             REPORTER_ASSERT_MESSAGE(reporter,
119                 strcmp(test[i].names[nameIndex].name, record.name.c_str()) == 0,
120                 "Name did not match."
121             );
122 
123             REPORTER_ASSERT_MESSAGE(reporter,
124                 strcmp(test[i].names[nameIndex].language, record.language.c_str()) == 0,
125                 "Language did not match."
126             );
127 
128             //printf("%s <%s>\n", record.name.c_str(), record.language.c_str());
129 
130             ++nameIndex;
131         }
132 
133         REPORTER_ASSERT_MESSAGE(reporter, nameIndex == test[i].nameCount,
134                                 "Fewer names than expected.");
135 
136         REPORTER_ASSERT_MESSAGE(reporter, !iter.next(record),
137                                 "More names than expected.");
138     }
139 }
140 
141 #define MAX_FAMILIES 1000
test_systemfonts(skiatest::Reporter * reporter,bool verbose)142 static void test_systemfonts(skiatest::Reporter* reporter, bool verbose) {
143     static const SkFontTableTag nameTag = SkSetFourByteTag('n','a','m','e');
144 
145     SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
146     int count = SkMin32(fm->countFamilies(), MAX_FAMILIES);
147     for (int i = 0; i < count; ++i) {
148         SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
149         for (int j = 0; j < set->count(); ++j) {
150             SkString sname;
151             SkFontStyle fs;
152             set->getStyle(j, &fs, &sname);
153 
154             SkAutoTUnref<SkTypeface> typeface(set->createTypeface(j));
155             if (NULL == typeface.get()) {
156                 //TODO: SkFontMgr_fontconfig always returns NULL?
157                 continue;
158             }
159 
160             SkString familyName;
161             typeface->getFamilyName(&familyName);
162             if (verbose) {
163                 SkDebugf("[%s]\n", familyName.c_str());
164             }
165 
166             SkAutoTUnref<SkTypeface::LocalizedStrings> familyNamesIter(
167                 typeface->createFamilyNameIterator());
168             SkTypeface::LocalizedString familyNameLocalized;
169             while (familyNamesIter->next(&familyNameLocalized)) {
170                 if (verbose) {
171                     SkDebugf("(%s) <%s>\n", familyNameLocalized.fString.c_str(),
172                                           familyNameLocalized.fLanguage.c_str());
173                 }
174             }
175 
176             size_t nameTableSize = typeface->getTableSize(nameTag);
177             if (0 == nameTableSize) {
178                 continue;
179             }
180             SkAutoTMalloc<uint8_t> nameTableData(nameTableSize);
181             size_t copied = typeface->getTableData(nameTag, 0, nameTableSize, nameTableData.get());
182             if (copied != nameTableSize) {
183                 continue;
184             }
185 
186             SkOTTableName::Iterator::Record record;
187             SkOTTableName::Iterator familyNameIter(*((SkOTTableName*)nameTableData.get()),
188                 SkOTTableName::Record::NameID::Predefined::FontFamilyName);
189             while (familyNameIter.next(record)) {
190                 REPORTER_ASSERT_MESSAGE(reporter,
191                     SkOTTableName::Record::NameID::Predefined::FontFamilyName == record.type,
192                     "Requested family name, got something else."
193                 );
194                 if (verbose) {
195                     SkDebugf("{%s} <%s>\n", record.name.c_str(), record.language.c_str());
196                 }
197             }
198 
199             SkOTTableName::Iterator styleNameIter(*((SkOTTableName*)nameTableData.get()),
200                 SkOTTableName::Record::NameID::Predefined::FontSubfamilyName);
201             while (styleNameIter.next(record)) {
202                 REPORTER_ASSERT_MESSAGE(reporter,
203                     SkOTTableName::Record::NameID::Predefined::FontSubfamilyName == record.type,
204                     "Requested subfamily name, got something else."
205                 );
206                 if (verbose) {
207                     SkDebugf("{{%s}} <%s>\n", record.name.c_str(), record.language.c_str());
208                 }
209             }
210 
211             if (verbose) {
212                 SkDebugf("\n");
213             }
214         }
215     }
216 }
217 
218 DEFINE_bool(verboseFontNames, false, "verbose FontNames test.");
219 
DEF_TEST(FontNames,reporter)220 DEF_TEST(FontNames, reporter) {
221     test_synthetic(reporter, FLAGS_verboseFontNames);
222     test_systemfonts(reporter, FLAGS_verboseFontNames);
223 }
224