FontNamesTest.cpp 7.8 KB

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