blob: 18ba35695e0482f721d185e7a9b7422808a3693f [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));
156
157 SkString familyName;
158 typeface->getFamilyName(&familyName);
159 if (verbose) {
160 printf("[%s]\n", familyName.c_str());
161 }
162
163 SkAutoTDelete<SkTypeface::LocalizedStrings> familyNamesIter(typeface->getFamilyNames());
164 SkTypeface::LocalizedString familyNameLocalized;
165 while (familyNamesIter->next(&familyNameLocalized)) {
166 if (verbose) {
167 printf("(%s) <%s>\n", familyNameLocalized.fString.c_str(),
168 familyNameLocalized.fLanguage.c_str());
169 }
170 }
171
172 size_t nameTableSize = typeface->getTableSize(nameTag);
173 if (0 == nameTableSize) {
174 continue;
175 }
176 SkAutoTMalloc<uint8_t> nameTableData(nameTableSize);
177 size_t copied = typeface->getTableData(nameTag, 0, nameTableSize, nameTableData.get());
178 if (copied != nameTableSize) {
179 continue;
180 }
181
182 SkOTTableName::Iterator::Record record;
183 SkOTTableName::Iterator familyNameIter(*((SkOTTableName*)nameTableData.get()),
184 SkOTTableName::Record::NameID::Predefined::FontFamilyName);
185 while (familyNameIter.next(record)) {
186 REPORTER_ASSERT_MESSAGE(reporter,
187 SkOTTableName::Record::NameID::Predefined::FontFamilyName == record.type,
188 "Requested family name, got something else."
189 );
190 if (verbose) {
191 printf("{%s} <%s>\n", record.name.c_str(), record.language.c_str());
192 }
193 }
194
195 SkOTTableName::Iterator styleNameIter(*((SkOTTableName*)nameTableData.get()),
196 SkOTTableName::Record::NameID::Predefined::FontSubfamilyName);
197 while (styleNameIter.next(record)) {
198 REPORTER_ASSERT_MESSAGE(reporter,
199 SkOTTableName::Record::NameID::Predefined::FontSubfamilyName == record.type,
200 "Requested subfamily name, got something else."
201 );
202 if (verbose) {
203 printf("{{%s}} <%s>\n", record.name.c_str(), record.language.c_str());
204 }
205 }
206
207 if (verbose) {
208 printf("\n");
209 }
210 }
211 }
212}
213
214DEFINE_bool(verboseFontNames, false, "verbose FontNames test.");
215
216static void TestFontNames(skiatest::Reporter* reporter) {
217 test_synthetic(reporter, FLAGS_verboseFontNames);
218 test_systemfonts(reporter, FLAGS_verboseFontNames);
219}
bungeman@google.com07a69f82013-04-02 14:12:38 +0000220
221#include "TestClassDef.h"
222DEFINE_TESTCLASS("FontNames", FontNamesTestClass, TestFontNames)