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