SkWhitelistTypefaces.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * Copyright 2015 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/SkStream.h"
  8. #include "include/core/SkString.h"
  9. #include "include/core/SkTypeface.h"
  10. #include "src/core/SkFontDescriptor.h"
  11. #include "src/core/SkOpts.h"
  12. #include "src/sfnt/SkOTUtils.h"
  13. #include "src/utils/SkUTF.h"
  14. #include "SkWhitelistChecksums.inc"
  15. #define WHITELIST_DEBUG 0
  16. extern void WhitelistSerializeTypeface(const SkTypeface*, SkWStream* );
  17. sk_sp<SkTypeface> WhitelistDeserializeTypeface(SkStream* );
  18. extern bool CheckChecksums();
  19. extern bool GenerateChecksums();
  20. #if WHITELIST_DEBUG
  21. static bool timesNewRomanSerializedNameOnly = false;
  22. #endif
  23. #define SUBNAME_PREFIX "sk_"
  24. static bool font_name_is_local(const char* fontName, SkFontStyle style) {
  25. if (!strcmp(fontName, "DejaVu Sans")) {
  26. return true;
  27. }
  28. sk_sp<SkTypeface> defaultFace(SkTypeface::MakeFromName(nullptr, style));
  29. sk_sp<SkTypeface> foundFace(SkTypeface::MakeFromName(fontName, style));
  30. return defaultFace != foundFace;
  31. }
  32. static int whitelist_name_index(const SkTypeface* tf) {
  33. SkString fontNameStr;
  34. sk_sp<SkTypeface::LocalizedStrings> nameIter =
  35. SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*tf);
  36. SkTypeface::LocalizedString familyNameLocalized;
  37. while (nameIter->next(&familyNameLocalized)) {
  38. fontNameStr = familyNameLocalized.fString;
  39. // check against permissible list of names
  40. for (int i = 0; i < whitelistCount; ++i) {
  41. if (fontNameStr.equals(whitelist[i].fFontName)) {
  42. return i;
  43. }
  44. }
  45. }
  46. #if WHITELIST_DEBUG
  47. sk_sp<SkTypeface::LocalizedStrings> debugIter =
  48. SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*tf);
  49. while (debugIter->next(&familyNameLocalized)) {
  50. SkDebugf("no match fontName=\"%s\"\n", familyNameLocalized.fString.c_str());
  51. }
  52. #endif
  53. return -1;
  54. }
  55. static uint32_t compute_checksum(const SkTypeface* tf) {
  56. std::unique_ptr<SkFontData> fontData = tf->makeFontData();
  57. if (!fontData) {
  58. return 0;
  59. }
  60. SkStreamAsset* fontStream = fontData->getStream();
  61. if (!fontStream) {
  62. return 0;
  63. }
  64. SkTDArray<char> data;
  65. size_t length = fontStream->getLength();
  66. if (!length) {
  67. return 0;
  68. }
  69. data.setCount((int) length);
  70. if (!fontStream->peek(data.begin(), length)) {
  71. return 0;
  72. }
  73. return SkOpts::hash(data.begin(), length);
  74. }
  75. static void serialize_sub(const char* fontName, SkFontStyle style, SkWStream* wstream) {
  76. SkFontDescriptor desc;
  77. SkString subName(SUBNAME_PREFIX);
  78. subName.append(fontName);
  79. const char* familyName = subName.c_str();
  80. desc.setFamilyName(familyName);
  81. desc.setStyle(style);
  82. desc.serialize(wstream);
  83. #if WHITELIST_DEBUG
  84. for (int i = 0; i < whitelistCount; ++i) {
  85. if (!strcmp(fontName, whitelist[i].fFontName)) {
  86. if (!whitelist[i].fSerializedSub) {
  87. whitelist[i].fSerializedSub = true;
  88. SkDebugf("%s %s\n", __FUNCTION__, familyName);
  89. }
  90. break;
  91. }
  92. }
  93. #endif
  94. }
  95. static bool is_local(const SkTypeface* tf) {
  96. bool isLocal = false;
  97. SkFontDescriptor desc;
  98. tf->getFontDescriptor(&desc, &isLocal);
  99. return isLocal;
  100. }
  101. static void serialize_full(const SkTypeface* tf, SkWStream* wstream) {
  102. bool isLocal = false;
  103. SkFontDescriptor desc;
  104. tf->getFontDescriptor(&desc, &isLocal);
  105. // Embed font data if it's a local font.
  106. if (isLocal && !desc.hasFontData()) {
  107. desc.setFontData(tf->makeFontData());
  108. }
  109. desc.serialize(wstream);
  110. }
  111. static void serialize_name_only(const SkTypeface* tf, SkWStream* wstream) {
  112. bool isLocal = false;
  113. SkFontDescriptor desc;
  114. tf->getFontDescriptor(&desc, &isLocal);
  115. SkASSERT(!isLocal);
  116. #if WHITELIST_DEBUG
  117. const char* familyName = desc.getFamilyName();
  118. if (familyName) {
  119. if (!strcmp(familyName, "Times New Roman")) {
  120. if (!timesNewRomanSerializedNameOnly) {
  121. timesNewRomanSerializedNameOnly = true;
  122. SkDebugf("%s %s\n", __FUNCTION__, familyName);
  123. }
  124. } else {
  125. for (int i = 0; i < whitelistCount; ++i) {
  126. if (!strcmp(familyName, whitelist[i].fFontName)) {
  127. if (!whitelist[i].fSerializedNameOnly) {
  128. whitelist[i].fSerializedNameOnly = true;
  129. SkDebugf("%s %s\n", __FUNCTION__, familyName);
  130. }
  131. break;
  132. }
  133. }
  134. }
  135. }
  136. #endif
  137. desc.serialize(wstream);
  138. }
  139. void WhitelistSerializeTypeface(const SkTypeface* tf, SkWStream* wstream) {
  140. if (!is_local(tf)) {
  141. serialize_name_only(tf, wstream);
  142. return;
  143. }
  144. int whitelistIndex = whitelist_name_index(tf);
  145. if (whitelistIndex < 0) {
  146. serialize_full(tf, wstream);
  147. return;
  148. }
  149. const char* fontName = whitelist[whitelistIndex].fFontName;
  150. if (!font_name_is_local(fontName, tf->fontStyle())) {
  151. #if WHITELIST_DEBUG
  152. SkDebugf("name not found locally \"%s\" style=%d\n", fontName, tf->style());
  153. #endif
  154. serialize_full(tf, wstream);
  155. return;
  156. }
  157. uint32_t checksum = compute_checksum(tf);
  158. if (whitelist[whitelistIndex].fChecksum != checksum) {
  159. #if WHITELIST_DEBUG
  160. if (whitelist[whitelistIndex].fChecksum) {
  161. SkDebugf("!!! checksum changed !!!\n");
  162. }
  163. SkDebugf("checksum updated\n");
  164. SkDebugf(" { \"%s\", 0x%08x },\n", fontName, checksum);
  165. #endif
  166. whitelist[whitelistIndex].fChecksum = checksum;
  167. }
  168. serialize_sub(fontName, tf->fontStyle(), wstream);
  169. }
  170. sk_sp<SkTypeface> WhitelistDeserializeTypeface(SkStream* stream) {
  171. SkFontDescriptor desc;
  172. if (!SkFontDescriptor::Deserialize(stream, &desc)) {
  173. return nullptr;
  174. }
  175. std::unique_ptr<SkFontData> data = desc.detachFontData();
  176. if (data) {
  177. sk_sp<SkTypeface> typeface(SkTypeface::MakeFromFontData(std::move(data)));
  178. if (typeface) {
  179. return typeface;
  180. }
  181. }
  182. const char* familyName = desc.getFamilyName();
  183. if (!strncmp(SUBNAME_PREFIX, familyName, sizeof(SUBNAME_PREFIX) - 1)) {
  184. familyName += sizeof(SUBNAME_PREFIX) - 1;
  185. }
  186. return SkTypeface::MakeFromName(familyName, desc.getStyle());
  187. }
  188. bool CheckChecksums() {
  189. for (int i = 0; i < whitelistCount; ++i) {
  190. const char* fontName = whitelist[i].fFontName;
  191. sk_sp<SkTypeface> tf(SkTypeface::MakeFromName(fontName, SkFontStyle()));
  192. uint32_t checksum = compute_checksum(tf.get());
  193. if (whitelist[i].fChecksum != checksum) {
  194. return false;
  195. }
  196. }
  197. return true;
  198. }
  199. const char checksumFileName[] = "SkWhitelistChecksums.inc";
  200. const char checksumHeader[] =
  201. "/*" "\n"
  202. " * Copyright 2015 Google Inc." "\n"
  203. " *" "\n"
  204. " * Use of this source code is governed by a BSD-style license that can be" "\n"
  205. " * found in the LICENSE file." "\n"
  206. " *" "\n"
  207. " * %s() in %s generated %s." "\n"
  208. " * Run 'whitelist_typefaces --generate' to create anew." "\n"
  209. " */" "\n"
  210. "" "\n"
  211. "#include \"SkTDArray.h\"" "\n"
  212. "" "\n"
  213. "struct Whitelist {" "\n"
  214. " const char* fFontName;" "\n"
  215. " uint32_t fChecksum;" "\n"
  216. " bool fSerializedNameOnly;" "\n"
  217. " bool fSerializedSub;" "\n"
  218. "};" "\n"
  219. "" "\n"
  220. "static Whitelist whitelist[] = {" "\n";
  221. const char checksumEntry[] =
  222. " { \"%s\", 0x%08x, false, false }," "\n";
  223. const char checksumTrailer[] =
  224. "};" "\n"
  225. "" "\n"
  226. "static const int whitelistCount = (int) SK_ARRAY_COUNT(whitelist);" "\n";
  227. #include "src/core/SkOSFile.h"
  228. bool GenerateChecksums() {
  229. FILE* file = sk_fopen(checksumFileName, kWrite_SkFILE_Flag);
  230. if (!file) {
  231. SkDebugf("Can't open %s for writing.\n", checksumFileName);
  232. return false;
  233. }
  234. SkString line;
  235. line.printf(checksumHeader, __FUNCTION__, __FILE__, checksumFileName);
  236. sk_fwrite(line.c_str(), line.size(), file);
  237. for (int i = 0; i < whitelistCount; ++i) {
  238. const char* fontName = whitelist[i].fFontName;
  239. sk_sp<SkTypeface> tf(SkTypeface::MakeFromName(fontName, SkFontStyle()));
  240. uint32_t checksum = compute_checksum(tf.get());
  241. line.printf(checksumEntry, fontName, checksum);
  242. sk_fwrite(line.c_str(), line.size(), file);
  243. }
  244. sk_fwrite(checksumTrailer, sizeof(checksumTrailer) - 1, file);
  245. sk_fclose(file);
  246. return true;
  247. }