create_test_font.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * Copyright 2014 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. // Running create_test_font generates ./tools/fonts/test_font_index.inc
  8. // and ./tools/fonts/test_font_<generic name>.inc which are read by
  9. // ./tools/fonts/TestFontMgr.cpp
  10. #include "include/core/SkFont.h"
  11. #include "include/core/SkFontMetrics.h"
  12. #include "include/core/SkFontStyle.h"
  13. #include "include/core/SkPath.h"
  14. #include "include/core/SkStream.h"
  15. #include "include/core/SkTypeface.h"
  16. #include "include/private/SkTArray.h"
  17. #include "src/core/SkOSFile.h"
  18. #include "src/core/SkSpan.h"
  19. #include "src/core/SkTSort.h"
  20. #include "src/utils/SkOSPath.h"
  21. #include "src/utils/SkUTF.h"
  22. #include <stdio.h>
  23. namespace {
  24. struct NamedFontStyle {
  25. char const * const fName;
  26. char const * const fIdentifierName;
  27. SkFontStyle const fStyle;
  28. };
  29. struct FontDesc {
  30. NamedFontStyle const fNamedStyle;
  31. char const * const fFile;
  32. };
  33. struct FontFamilyDesc {
  34. char const * const fGenericName;
  35. char const * const fFamilyName;
  36. char const * const fIdentifierName;
  37. SkSpan<const FontDesc> const fFonts;
  38. };
  39. } // namespace
  40. static FILE* font_header(const char* family) {
  41. SkString outPath(SkOSPath::Join(".", "tools"));
  42. outPath = SkOSPath::Join(outPath.c_str(), "fonts");
  43. outPath = SkOSPath::Join(outPath.c_str(), "test_font_");
  44. SkString fam(family);
  45. do {
  46. int dashIndex = fam.find("-");
  47. if (dashIndex < 0) {
  48. break;
  49. }
  50. fam.writable_str()[dashIndex] = '_';
  51. } while (true);
  52. outPath.append(fam);
  53. outPath.append(".inc");
  54. FILE* out = fopen(outPath.c_str(), "w");
  55. static const char kHeader[] =
  56. "/*\n"
  57. " * Copyright 2015 Google Inc.\n"
  58. " *\n"
  59. " * Use of this source code is governed by a BSD-style license that can be\n"
  60. " * found in the LICENSE file.\n"
  61. " */\n"
  62. "\n"
  63. "// Auto-generated by ";
  64. fprintf(out, "%s%s\n\n", kHeader, SkOSPath::Basename(__FILE__).c_str());
  65. return out;
  66. }
  67. enum {
  68. kMaxLineLength = 80,
  69. };
  70. static ptrdiff_t last_line_length(const SkString& str) {
  71. const char* first = str.c_str();
  72. const char* last = first + str.size();
  73. const char* ptr = last;
  74. while (ptr > first && *--ptr != '\n')
  75. ;
  76. return last - ptr - 1;
  77. }
  78. static void output_fixed(SkScalar num, int emSize, SkString* out) {
  79. int hex = (int) (num * 65536 / emSize);
  80. out->appendf("0x%08x,", hex);
  81. *out += (int) last_line_length(*out) >= kMaxLineLength ? '\n' : ' ';
  82. }
  83. static void output_scalar(SkScalar num, int emSize, SkString* out) {
  84. num /= emSize;
  85. if (num == (int) num) {
  86. out->appendS32((int) num);
  87. } else {
  88. SkString str;
  89. str.printf("%1.6g", num);
  90. int width = (int) str.size();
  91. const char* cStr = str.c_str();
  92. while (cStr[width - 1] == '0') {
  93. --width;
  94. }
  95. str.remove(width, str.size() - width);
  96. out->appendf("%sf", str.c_str());
  97. }
  98. *out += ',';
  99. *out += (int) last_line_length(*out) >= kMaxLineLength ? '\n' : ' ';
  100. }
  101. static int output_points(const SkPoint* pts, int emSize, int count, SkString* ptsOut) {
  102. for (int index = 0; index < count; ++index) {
  103. output_scalar(pts[index].fX, emSize, ptsOut);
  104. output_scalar(pts[index].fY, emSize, ptsOut);
  105. }
  106. return count;
  107. }
  108. static void output_path_data(const SkFont& font,
  109. int emSize, SkString* ptsOut, SkTDArray<SkPath::Verb>* verbs,
  110. SkTDArray<unsigned>* charCodes, SkTDArray<SkScalar>* widths) {
  111. for (SkUnichar index = 0x00; index < 0x7f; ++index) {
  112. uint16_t glyphID = font.unicharToGlyph(index);
  113. SkPath path;
  114. font.getPath(glyphID, &path);
  115. SkPath::RawIter iter(path);
  116. SkPath::Verb verb;
  117. SkPoint pts[4];
  118. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  119. *verbs->append() = verb;
  120. switch (verb) {
  121. case SkPath::kMove_Verb:
  122. output_points(&pts[0], emSize, 1, ptsOut);
  123. break;
  124. case SkPath::kLine_Verb:
  125. output_points(&pts[1], emSize, 1, ptsOut);
  126. break;
  127. case SkPath::kQuad_Verb:
  128. output_points(&pts[1], emSize, 2, ptsOut);
  129. break;
  130. case SkPath::kCubic_Verb:
  131. output_points(&pts[1], emSize, 3, ptsOut);
  132. break;
  133. case SkPath::kClose_Verb:
  134. break;
  135. default:
  136. SkDEBUGFAIL("bad verb");
  137. SkASSERT(0);
  138. }
  139. }
  140. *verbs->append() = SkPath::kDone_Verb;
  141. *charCodes->append() = index;
  142. SkScalar width;
  143. font.getWidths(&glyphID, 1, &width);
  144. // SkASSERT(floor(width) == width); // not true for Hiragino Maru Gothic Pro
  145. *widths->append() = width;
  146. if (0 == index) {
  147. index = 0x1f; // skip the rest of the control codes
  148. }
  149. }
  150. }
  151. static int offset_str_len(unsigned num) {
  152. if (num == (unsigned) -1) {
  153. return 10;
  154. }
  155. unsigned result = 1;
  156. unsigned ref = 10;
  157. while (ref <= num) {
  158. ++result;
  159. ref *= 10;
  160. }
  161. return result;
  162. }
  163. static SkString strip_final(const SkString& str) {
  164. SkString result(str);
  165. if (result.endsWith("\n")) {
  166. result.remove(result.size() - 1, 1);
  167. }
  168. if (result.endsWith(" ")) {
  169. result.remove(result.size() - 1, 1);
  170. }
  171. if (result.endsWith(",")) {
  172. result.remove(result.size() - 1, 1);
  173. }
  174. return result;
  175. }
  176. static void output_font(sk_sp<SkTypeface> face, const char* identifier, FILE* out) {
  177. const int emSize = face->getUnitsPerEm() * 2;
  178. SkFont font;
  179. font.setEdging(SkFont::Edging::kAntiAlias);
  180. font.setSize(emSize);
  181. font.setTypeface(std::move(face));
  182. SkTDArray<SkPath::Verb> verbs;
  183. SkTDArray<unsigned> charCodes;
  184. SkTDArray<SkScalar> widths;
  185. SkString ptsOut;
  186. output_path_data(font, emSize, &ptsOut, &verbs, &charCodes, &widths);
  187. fprintf(out, "const SkScalar %sPoints[] = {\n", identifier);
  188. ptsOut = strip_final(ptsOut);
  189. fprintf(out, "%s", ptsOut.c_str());
  190. fprintf(out, "\n};\n\n");
  191. fprintf(out, "const unsigned char %sVerbs[] = {\n", identifier);
  192. int verbCount = verbs.count();
  193. int outChCount = 0;
  194. for (int index = 0; index < verbCount;) {
  195. SkPath::Verb verb = verbs[index];
  196. SkASSERT(verb >= SkPath::kMove_Verb && verb <= SkPath::kDone_Verb);
  197. SkASSERT(SkTFitsIn<uint8_t>(verb));
  198. fprintf(out, "%u", verb);
  199. if (++index < verbCount) {
  200. outChCount += 3;
  201. fprintf(out, "%c", ',');
  202. if (outChCount >= kMaxLineLength) {
  203. outChCount = 0;
  204. fprintf(out, "%c", '\n');
  205. } else {
  206. fprintf(out, "%c", ' ');
  207. }
  208. }
  209. }
  210. fprintf(out, "\n};\n\n");
  211. // all fonts are now 0x00, 0x20 - 0xFE
  212. // don't need to generate or output character codes?
  213. fprintf(out, "const SkUnichar %sCharCodes[] = {\n", identifier);
  214. int offsetCount = charCodes.count();
  215. for (int index = 0; index < offsetCount;) {
  216. unsigned offset = charCodes[index];
  217. fprintf(out, "%u", offset);
  218. if (++index < offsetCount) {
  219. outChCount += offset_str_len(offset) + 2;
  220. fprintf(out, "%c", ',');
  221. if (outChCount >= kMaxLineLength) {
  222. outChCount = 0;
  223. fprintf(out, "%c", '\n');
  224. } else {
  225. fprintf(out, "%c", ' ');
  226. }
  227. }
  228. }
  229. fprintf(out, "\n};\n\n");
  230. SkString widthsStr;
  231. fprintf(out, "const SkFixed %sWidths[] = {\n", identifier);
  232. for (int index = 0; index < offsetCount; ++index) {
  233. output_fixed(widths[index], emSize, &widthsStr);
  234. }
  235. widthsStr = strip_final(widthsStr);
  236. fprintf(out, "%s\n};\n\n", widthsStr.c_str());
  237. fprintf(out, "const size_t %sCharCodesCount = SK_ARRAY_COUNT(%sCharCodes);\n\n",
  238. identifier, identifier);
  239. SkFontMetrics metrics;
  240. font.getMetrics(&metrics);
  241. fprintf(out, "const SkFontMetrics %sMetrics = {\n", identifier);
  242. SkString metricsStr;
  243. metricsStr.printf("0x%08x, ", metrics.fFlags);
  244. output_scalar(metrics.fTop, emSize, &metricsStr);
  245. output_scalar(metrics.fAscent, emSize, &metricsStr);
  246. output_scalar(metrics.fDescent, emSize, &metricsStr);
  247. output_scalar(metrics.fBottom, emSize, &metricsStr);
  248. output_scalar(metrics.fLeading, emSize, &metricsStr);
  249. output_scalar(metrics.fAvgCharWidth, emSize, &metricsStr);
  250. output_scalar(metrics.fMaxCharWidth, emSize, &metricsStr);
  251. output_scalar(metrics.fXMin, emSize, &metricsStr);
  252. output_scalar(metrics.fXMax, emSize, &metricsStr);
  253. output_scalar(metrics.fXHeight, emSize, &metricsStr);
  254. output_scalar(metrics.fCapHeight, emSize, &metricsStr);
  255. output_scalar(metrics.fUnderlineThickness, emSize, &metricsStr);
  256. output_scalar(metrics.fUnderlinePosition, emSize, &metricsStr);
  257. output_scalar(metrics.fStrikeoutThickness, emSize, &metricsStr);
  258. output_scalar(metrics.fStrikeoutPosition, emSize, &metricsStr);
  259. metricsStr = strip_final(metricsStr);
  260. fprintf(out, "%s\n};\n\n", metricsStr.c_str());
  261. }
  262. static SkString identifier(const FontFamilyDesc& family, const FontDesc& font) {
  263. SkString id(family.fIdentifierName);
  264. id.append(font.fNamedStyle.fIdentifierName);
  265. return id;
  266. }
  267. static void generate_fonts(const char* basepath, const SkSpan<const FontFamilyDesc>& families) {
  268. FILE* out = nullptr;
  269. for (const FontFamilyDesc& family : families) {
  270. out = font_header(family.fGenericName);
  271. for (const FontDesc& font : family.fFonts) {
  272. SkString filepath(SkOSPath::Join(basepath, font.fFile));
  273. SkASSERTF(sk_exists(filepath.c_str()), "The file %s does not exist.", filepath.c_str());
  274. sk_sp<SkTypeface> resourceTypeface = SkTypeface::MakeFromFile(filepath.c_str());
  275. SkASSERTF(resourceTypeface, "The file %s is not a font.", filepath.c_str());
  276. output_font(std::move(resourceTypeface), identifier(family, font).c_str(), out);
  277. }
  278. fclose(out);
  279. }
  280. }
  281. static const char* slant_to_string(SkFontStyle::Slant slant) {
  282. switch (slant) {
  283. case SkFontStyle::kUpright_Slant: return "SkFontStyle::kUpright_Slant";
  284. case SkFontStyle::kItalic_Slant : return "SkFontStyle::kItalic_Slant" ;
  285. case SkFontStyle::kOblique_Slant: return "SkFontStyle::kOblique_Slant";
  286. default: SK_ABORT("Unknown slant"); return "";
  287. }
  288. }
  289. static void generate_index(const SkSpan<const FontFamilyDesc>& families,
  290. const FontDesc* defaultFont)
  291. {
  292. FILE* out = font_header("index");
  293. fprintf(out, "static SkTestFontData gTestFonts[] = {\n");
  294. for (const FontFamilyDesc& family : families) {
  295. for (const FontDesc& font : family.fFonts) {
  296. SkString identifierStr = identifier(family, font);
  297. const char* identifier = identifierStr.c_str();
  298. const SkFontStyle& style = font.fNamedStyle.fStyle;
  299. fprintf(out,
  300. " { %sPoints, %sVerbs,\n"
  301. " %sCharCodes, %sCharCodesCount, %sWidths,\n"
  302. " %sMetrics, \"Toy %s\", SkFontStyle(%d,%d,%s)\n"
  303. " },\n",
  304. identifier, identifier,
  305. identifier, identifier, identifier,
  306. identifier, family.fFamilyName,
  307. style.weight(), style.width(), slant_to_string(style.slant()));
  308. }
  309. }
  310. fprintf(out, "};\n\n");
  311. fprintf(out,
  312. "struct SubFont {\n"
  313. " const char* fFamilyName;\n"
  314. " const char* fStyleName;\n"
  315. " SkFontStyle fStyle;\n"
  316. " SkTestFontData& fFont;\n"
  317. " const char* fFile;\n"
  318. "};\n\n"
  319. "const SubFont gSubFonts[] = {\n");
  320. int defaultIndex = -1;
  321. int testFontsIndex = 0;
  322. for (const FontFamilyDesc& family : families) {
  323. for (const FontDesc& font : family.fFonts) {
  324. if (&font == defaultFont) {
  325. defaultIndex = testFontsIndex;
  326. }
  327. const SkFontStyle& style = font.fNamedStyle.fStyle;
  328. fprintf(out,
  329. " { \"%s\", \"%s\", SkFontStyle(%d,%d,%s), gTestFonts[%d], \"%s\" },\n",
  330. family.fGenericName, font.fNamedStyle.fName,
  331. style.weight(), style.width(), slant_to_string(style.slant()),
  332. testFontsIndex, font.fFile);
  333. testFontsIndex++;
  334. }
  335. }
  336. testFontsIndex = 0;
  337. for (const FontFamilyDesc& family : families) {
  338. for (const FontDesc& font : family.fFonts) {
  339. fprintf(out,
  340. " { \"Toy %s\", \"%s\", SkFontStyle(%d,%d,%s), gTestFonts[%d], \"%s\" },\n",
  341. family.fFamilyName, font.fNamedStyle.fName,
  342. font.fNamedStyle.fStyle.weight(), font.fNamedStyle.fStyle.width(),
  343. slant_to_string(font.fNamedStyle.fStyle.slant()), testFontsIndex, font.fFile);
  344. testFontsIndex++;
  345. }
  346. }
  347. fprintf(out, "};\n\n");
  348. SkASSERT(defaultIndex >= 0);
  349. fprintf(out, "const size_t gDefaultFontIndex = %d;\n", defaultIndex);
  350. fclose(out);
  351. }
  352. int main(int , char * const []) {
  353. constexpr NamedFontStyle normal = {"Normal", "Normal", SkFontStyle::Normal() };
  354. constexpr NamedFontStyle bold = {"Bold", "Bold", SkFontStyle::Bold() };
  355. constexpr NamedFontStyle italic = {"Italic", "Italic", SkFontStyle::Italic() };
  356. constexpr NamedFontStyle bolditalic = {"Bold Italic", "BoldItalic", SkFontStyle::BoldItalic()};
  357. static constexpr FontDesc kMonoFonts[] = {
  358. {normal, "LiberationMono-Regular.ttf"},
  359. {bold, "LiberationMono-Bold.ttf"},
  360. {italic, "LiberationMono-Italic.ttf"},
  361. {bolditalic, "LiberationMono-BoldItalic.ttf"},
  362. };
  363. static constexpr FontDesc kSansFonts[] = {
  364. {normal, "LiberationSans-Regular.ttf"},
  365. {bold, "LiberationSans-Bold.ttf"},
  366. {italic, "LiberationSans-Italic.ttf"},
  367. {bolditalic, "LiberationSans-BoldItalic.ttf"},
  368. };
  369. static constexpr FontDesc kSerifFonts[] = {
  370. {normal, "LiberationSerif-Regular.ttf"},
  371. {bold, "LiberationSerif-Bold.ttf"},
  372. {italic, "LiberationSerif-Italic.ttf"},
  373. {bolditalic, "LiberationSerif-BoldItalic.ttf"},
  374. };
  375. static constexpr FontFamilyDesc kFamiliesData[] = {
  376. {"monospace", "Liberation Mono", "LiberationMono", SkMakeSpan(kMonoFonts)},
  377. {"sans-serif", "Liberation Sans", "LiberationSans", SkMakeSpan(kSansFonts)},
  378. {"serif", "Liberation Serif", "LiberationSerif", SkMakeSpan(kSerifFonts)},
  379. };
  380. static constexpr SkSpan<const FontFamilyDesc> kFamilies(SkMakeSpan(kFamiliesData));
  381. #ifdef SK_BUILD_FOR_UNIX
  382. generate_fonts("/usr/share/fonts/truetype/liberation/", kFamilies);
  383. #else
  384. generate_fonts("/Library/Fonts/", kFamilies);
  385. #endif
  386. generate_index(kFamilies, &kFamilies[1].fFonts[0]);
  387. return 0;
  388. }