SkFontMgr_android_parser.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. /*
  2. * Copyright 2011 The Android Open Source Project
  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. // Despite the name and location, this is portable code.
  8. #include "include/core/SkFontMgr.h"
  9. #include "include/core/SkStream.h"
  10. #include "include/private/SkFixed.h"
  11. #include "include/private/SkMalloc.h"
  12. #include "include/private/SkTDArray.h"
  13. #include "include/private/SkTLogic.h"
  14. #include "include/private/SkTemplates.h"
  15. #include "src/core/SkOSFile.h"
  16. #include "src/core/SkTSearch.h"
  17. #include "src/ports/SkFontMgr_android_parser.h"
  18. #include <expat.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #define LMP_SYSTEM_FONTS_FILE "/system/etc/fonts.xml"
  22. #define OLD_SYSTEM_FONTS_FILE "/system/etc/system_fonts.xml"
  23. #define FALLBACK_FONTS_FILE "/system/etc/fallback_fonts.xml"
  24. #define VENDOR_FONTS_FILE "/vendor/etc/fallback_fonts.xml"
  25. #define LOCALE_FALLBACK_FONTS_SYSTEM_DIR "/system/etc"
  26. #define LOCALE_FALLBACK_FONTS_VENDOR_DIR "/vendor/etc"
  27. #define LOCALE_FALLBACK_FONTS_PREFIX "fallback_fonts-"
  28. #define LOCALE_FALLBACK_FONTS_SUFFIX ".xml"
  29. #ifndef SK_FONT_FILE_PREFIX
  30. # define SK_FONT_FILE_PREFIX "/fonts/"
  31. #endif
  32. /**
  33. * This file contains TWO 'familyset' handlers:
  34. * One for JB and earlier which works with
  35. * /system/etc/system_fonts.xml
  36. * /system/etc/fallback_fonts.xml
  37. * /vendor/etc/fallback_fonts.xml
  38. * /system/etc/fallback_fonts-XX.xml
  39. * /vendor/etc/fallback_fonts-XX.xml
  40. * and the other for LMP and later which works with
  41. * /system/etc/fonts.xml
  42. *
  43. * If the 'familyset' 'version' attribute is 21 or higher the LMP parser is used, otherwise the JB.
  44. */
  45. struct FamilyData;
  46. struct TagHandler {
  47. /** Called at the start tag.
  48. * Called immediately after the parent tag retuns this handler from a call to 'tag'.
  49. * Allows setting up for handling the tag content and processing attributes.
  50. * If nullptr, will not be called.
  51. */
  52. void (*start)(FamilyData* data, const char* tag, const char** attributes);
  53. /** Called at the end tag.
  54. * Allows post-processing of any accumulated information.
  55. * This will be the last call made in relation to the current tag.
  56. * If nullptr, will not be called.
  57. */
  58. void (*end)(FamilyData* data, const char* tag);
  59. /** Called when a nested tag is encountered.
  60. * This is responsible for determining how to handle the tag.
  61. * If the tag is not recognized, return nullptr to skip the tag.
  62. * If nullptr, all nested tags will be skipped.
  63. */
  64. const TagHandler* (*tag)(FamilyData* data, const char* tag, const char** attributes);
  65. /** The character handler for this tag.
  66. * This is only active for character data contained directly in this tag (not sub-tags).
  67. * The first parameter will be castable to a FamilyData*.
  68. * If nullptr, any character data in this tag will be ignored.
  69. */
  70. XML_CharacterDataHandler chars;
  71. };
  72. /** Represents the current parsing state. */
  73. struct FamilyData {
  74. FamilyData(XML_Parser parser, SkTDArray<FontFamily*>& families,
  75. const SkString& basePath, bool isFallback, const char* filename,
  76. const TagHandler* topLevelHandler)
  77. : fParser(parser)
  78. , fFamilies(families)
  79. , fCurrentFamily(nullptr)
  80. , fCurrentFontInfo(nullptr)
  81. , fVersion(0)
  82. , fBasePath(basePath)
  83. , fIsFallback(isFallback)
  84. , fFilename(filename)
  85. , fDepth(1)
  86. , fSkip(0)
  87. , fHandler(&topLevelHandler, 1)
  88. { }
  89. XML_Parser fParser; // The expat parser doing the work, owned by caller
  90. SkTDArray<FontFamily*>& fFamilies; // The array to append families, owned by caller
  91. std::unique_ptr<FontFamily> fCurrentFamily; // The family being created, owned by this
  92. FontFileInfo* fCurrentFontInfo; // The info being created, owned by fCurrentFamily
  93. int fVersion; // The version of the file parsed.
  94. const SkString& fBasePath; // The current base path.
  95. const bool fIsFallback; // The file being parsed is a fallback file
  96. const char* fFilename; // The name of the file currently being parsed.
  97. int fDepth; // The current element depth of the parse.
  98. int fSkip; // The depth to stop skipping, 0 if not skipping.
  99. SkTDArray<const TagHandler*> fHandler; // The stack of current tag handlers.
  100. };
  101. static bool memeq(const char* s1, const char* s2, size_t n1, size_t n2) {
  102. return n1 == n2 && 0 == memcmp(s1, s2, n1);
  103. }
  104. #define MEMEQ(c, s, n) memeq(c, s, sizeof(c) - 1, n)
  105. #define ATTS_NON_NULL(a, i) (a[i] != nullptr && a[i+1] != nullptr)
  106. #define SK_FONTMGR_ANDROID_PARSER_PREFIX "[SkFontMgr Android Parser] "
  107. #define SK_FONTCONFIGPARSER_WARNING(message, ...) \
  108. SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "%s:%d:%d: warning: " message "\n", self->fFilename, \
  109. XML_GetCurrentLineNumber(self->fParser), XML_GetCurrentColumnNumber(self->fParser), \
  110. ##__VA_ARGS__)
  111. static bool is_whitespace(char c) {
  112. return c == ' ' || c == '\n'|| c == '\r' || c == '\t';
  113. }
  114. static void trim_string(SkString* s) {
  115. char* str = s->writable_str();
  116. const char* start = str; // start is inclusive
  117. const char* end = start + s->size(); // end is exclusive
  118. while (is_whitespace(*start)) { ++start; }
  119. if (start != end) {
  120. --end; // make end inclusive
  121. while (is_whitespace(*end)) { --end; }
  122. ++end; // make end exclusive
  123. }
  124. size_t len = end - start;
  125. memmove(str, start, len);
  126. s->resize(len);
  127. }
  128. namespace lmpParser {
  129. static const TagHandler axisHandler = {
  130. /*start*/[](FamilyData* self, const char* tag, const char** attributes) {
  131. FontFileInfo& file = *self->fCurrentFontInfo;
  132. SkFourByteTag axisTag = SkSetFourByteTag('\0','\0','\0','\0');
  133. SkFixed axisStyleValue = 0;
  134. bool axisTagIsValid = false;
  135. bool axisStyleValueIsValid = false;
  136. for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) {
  137. const char* name = attributes[i];
  138. const char* value = attributes[i+1];
  139. size_t nameLen = strlen(name);
  140. if (MEMEQ("tag", name, nameLen)) {
  141. size_t valueLen = strlen(value);
  142. if (valueLen == 4) {
  143. axisTag = SkSetFourByteTag(value[0], value[1], value[2], value[3]);
  144. axisTagIsValid = true;
  145. for (int j = 0; j < file.fVariationDesignPosition.count() - 1; ++j) {
  146. if (file.fVariationDesignPosition[j].axis == axisTag) {
  147. axisTagIsValid = false;
  148. SK_FONTCONFIGPARSER_WARNING("'%c%c%c%c' axis specified more than once",
  149. (axisTag >> 24) & 0xFF,
  150. (axisTag >> 16) & 0xFF,
  151. (axisTag >> 8) & 0xFF,
  152. (axisTag ) & 0xFF);
  153. }
  154. }
  155. } else {
  156. SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid axis tag", value);
  157. }
  158. } else if (MEMEQ("stylevalue", name, nameLen)) {
  159. if (parse_fixed<16>(value, &axisStyleValue)) {
  160. axisStyleValueIsValid = true;
  161. } else {
  162. SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid axis stylevalue", value);
  163. }
  164. }
  165. }
  166. if (axisTagIsValid && axisStyleValueIsValid) {
  167. auto& coordinate = file.fVariationDesignPosition.push_back();
  168. coordinate.axis = axisTag;
  169. coordinate.value = SkFixedToScalar(axisStyleValue);
  170. }
  171. },
  172. /*end*/nullptr,
  173. /*tag*/nullptr,
  174. /*chars*/nullptr,
  175. };
  176. static const TagHandler fontHandler = {
  177. /*start*/[](FamilyData* self, const char* tag, const char** attributes) {
  178. // 'weight' (non-negative integer) [default 0]
  179. // 'style' ("normal", "italic") [default "auto"]
  180. // 'index' (non-negative integer) [default 0]
  181. // The character data should be a filename.
  182. FontFileInfo& file = self->fCurrentFamily->fFonts.push_back();
  183. self->fCurrentFontInfo = &file;
  184. SkString fallbackFor;
  185. for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) {
  186. const char* name = attributes[i];
  187. const char* value = attributes[i+1];
  188. size_t nameLen = strlen(name);
  189. if (MEMEQ("weight", name, nameLen)) {
  190. if (!parse_non_negative_integer(value, &file.fWeight)) {
  191. SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid weight", value);
  192. }
  193. } else if (MEMEQ("style", name, nameLen)) {
  194. size_t valueLen = strlen(value);
  195. if (MEMEQ("normal", value, valueLen)) {
  196. file.fStyle = FontFileInfo::Style::kNormal;
  197. } else if (MEMEQ("italic", value, valueLen)) {
  198. file.fStyle = FontFileInfo::Style::kItalic;
  199. }
  200. } else if (MEMEQ("index", name, nameLen)) {
  201. if (!parse_non_negative_integer(value, &file.fIndex)) {
  202. SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid index", value);
  203. }
  204. } else if (MEMEQ("fallbackFor", name, nameLen)) {
  205. /** fallbackFor specifies a family fallback and should have been on family. */
  206. fallbackFor = value;
  207. }
  208. }
  209. if (!fallbackFor.isEmpty()) {
  210. std::unique_ptr<FontFamily>* fallbackFamily =
  211. self->fCurrentFamily->fallbackFamilies.find(fallbackFor);
  212. if (!fallbackFamily) {
  213. std::unique_ptr<FontFamily> newFallbackFamily(
  214. new FontFamily(self->fCurrentFamily->fBasePath, true));
  215. fallbackFamily = self->fCurrentFamily->fallbackFamilies.set(
  216. fallbackFor, std::move(newFallbackFamily));
  217. (*fallbackFamily)->fLanguages = self->fCurrentFamily->fLanguages;
  218. (*fallbackFamily)->fVariant = self->fCurrentFamily->fVariant;
  219. (*fallbackFamily)->fOrder = self->fCurrentFamily->fOrder;
  220. (*fallbackFamily)->fFallbackFor = fallbackFor;
  221. }
  222. self->fCurrentFontInfo = &(*fallbackFamily)->fFonts.emplace_back(file);
  223. self->fCurrentFamily->fFonts.pop_back();
  224. }
  225. },
  226. /*end*/[](FamilyData* self, const char* tag) {
  227. trim_string(&self->fCurrentFontInfo->fFileName);
  228. },
  229. /*tag*/[](FamilyData* self, const char* tag, const char** attributes) -> const TagHandler* {
  230. size_t len = strlen(tag);
  231. if (MEMEQ("axis", tag, len)) {
  232. return &axisHandler;
  233. }
  234. return nullptr;
  235. },
  236. /*chars*/[](void* data, const char* s, int len) {
  237. FamilyData* self = static_cast<FamilyData*>(data);
  238. self->fCurrentFontInfo->fFileName.append(s, len);
  239. }
  240. };
  241. static const TagHandler familyHandler = {
  242. /*start*/[](FamilyData* self, const char* tag, const char** attributes) {
  243. // 'name' (string) [optional]
  244. // 'lang' (space separated string) [default ""]
  245. // 'variant' ("elegant", "compact") [default "default"]
  246. // If there is no name, this is a fallback only font.
  247. FontFamily* family = new FontFamily(self->fBasePath, true);
  248. self->fCurrentFamily.reset(family);
  249. for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) {
  250. const char* name = attributes[i];
  251. const char* value = attributes[i+1];
  252. size_t nameLen = strlen(name);
  253. size_t valueLen = strlen(value);
  254. if (MEMEQ("name", name, nameLen)) {
  255. SkAutoAsciiToLC tolc(value);
  256. family->fNames.push_back().set(tolc.lc());
  257. family->fIsFallbackFont = false;
  258. } else if (MEMEQ("lang", name, nameLen)) {
  259. size_t i = 0;
  260. while (true) {
  261. for (; i < valueLen && is_whitespace(value[i]); ++i) { }
  262. if (i == valueLen) { break; }
  263. size_t j;
  264. for (j = i + 1; j < valueLen && !is_whitespace(value[j]); ++j) { }
  265. family->fLanguages.emplace_back(value + i, j - i);
  266. i = j;
  267. if (i == valueLen) { break; }
  268. }
  269. } else if (MEMEQ("variant", name, nameLen)) {
  270. if (MEMEQ("elegant", value, valueLen)) {
  271. family->fVariant = kElegant_FontVariant;
  272. } else if (MEMEQ("compact", value, valueLen)) {
  273. family->fVariant = kCompact_FontVariant;
  274. }
  275. }
  276. }
  277. },
  278. /*end*/[](FamilyData* self, const char* tag) {
  279. *self->fFamilies.append() = self->fCurrentFamily.release();
  280. },
  281. /*tag*/[](FamilyData* self, const char* tag, const char** attributes) -> const TagHandler* {
  282. size_t len = strlen(tag);
  283. if (MEMEQ("font", tag, len)) {
  284. return &fontHandler;
  285. }
  286. return nullptr;
  287. },
  288. /*chars*/nullptr,
  289. };
  290. static FontFamily* find_family(FamilyData* self, const SkString& familyName) {
  291. for (int i = 0; i < self->fFamilies.count(); i++) {
  292. FontFamily* candidate = self->fFamilies[i];
  293. for (int j = 0; j < candidate->fNames.count(); j++) {
  294. if (candidate->fNames[j] == familyName) {
  295. return candidate;
  296. }
  297. }
  298. }
  299. return nullptr;
  300. }
  301. static const TagHandler aliasHandler = {
  302. /*start*/[](FamilyData* self, const char* tag, const char** attributes) {
  303. // 'name' (string) introduces a new family name.
  304. // 'to' (string) specifies which (previous) family to alias
  305. // 'weight' (non-negative integer) [optional]
  306. // If it *does not* have a weight, 'name' is an alias for the entire 'to' family.
  307. // If it *does* have a weight, 'name' is a new family consisting of
  308. // the font(s) with 'weight' from the 'to' family.
  309. SkString aliasName;
  310. SkString to;
  311. int weight = 0;
  312. for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) {
  313. const char* name = attributes[i];
  314. const char* value = attributes[i+1];
  315. size_t nameLen = strlen(name);
  316. if (MEMEQ("name", name, nameLen)) {
  317. SkAutoAsciiToLC tolc(value);
  318. aliasName.set(tolc.lc());
  319. } else if (MEMEQ("to", name, nameLen)) {
  320. to.set(value);
  321. } else if (MEMEQ("weight", name, nameLen)) {
  322. if (!parse_non_negative_integer(value, &weight)) {
  323. SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid weight", value);
  324. }
  325. }
  326. }
  327. // Assumes that the named family is already declared
  328. FontFamily* targetFamily = find_family(self, to);
  329. if (!targetFamily) {
  330. SK_FONTCONFIGPARSER_WARNING("'%s' alias target not found", to.c_str());
  331. return;
  332. }
  333. if (weight) {
  334. FontFamily* family = new FontFamily(targetFamily->fBasePath, self->fIsFallback);
  335. family->fNames.push_back().set(aliasName);
  336. for (int i = 0; i < targetFamily->fFonts.count(); i++) {
  337. if (targetFamily->fFonts[i].fWeight == weight) {
  338. family->fFonts.push_back(targetFamily->fFonts[i]);
  339. }
  340. }
  341. *self->fFamilies.append() = family;
  342. } else {
  343. targetFamily->fNames.push_back().set(aliasName);
  344. }
  345. },
  346. /*end*/nullptr,
  347. /*tag*/nullptr,
  348. /*chars*/nullptr,
  349. };
  350. static const TagHandler familySetHandler = {
  351. /*start*/[](FamilyData* self, const char* tag, const char** attributes) { },
  352. /*end*/nullptr,
  353. /*tag*/[](FamilyData* self, const char* tag, const char** attributes) -> const TagHandler* {
  354. size_t len = strlen(tag);
  355. if (MEMEQ("family", tag, len)) {
  356. return &familyHandler;
  357. } else if (MEMEQ("alias", tag, len)) {
  358. return &aliasHandler;
  359. }
  360. return nullptr;
  361. },
  362. /*chars*/nullptr,
  363. };
  364. } // lmpParser
  365. namespace jbParser {
  366. static const TagHandler fileHandler = {
  367. /*start*/[](FamilyData* self, const char* tag, const char** attributes) {
  368. // 'variant' ("elegant", "compact") [default "default"]
  369. // 'lang' (string) [default ""]
  370. // 'index' (non-negative integer) [default 0]
  371. // The character data should be a filename.
  372. FontFamily& currentFamily = *self->fCurrentFamily.get();
  373. FontFileInfo& newFileInfo = currentFamily.fFonts.push_back();
  374. if (attributes) {
  375. for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) {
  376. const char* name = attributes[i];
  377. const char* value = attributes[i+1];
  378. size_t nameLen = strlen(name);
  379. size_t valueLen = strlen(value);
  380. if (MEMEQ("variant", name, nameLen)) {
  381. const FontVariant prevVariant = currentFamily.fVariant;
  382. if (MEMEQ("elegant", value, valueLen)) {
  383. currentFamily.fVariant = kElegant_FontVariant;
  384. } else if (MEMEQ("compact", value, valueLen)) {
  385. currentFamily.fVariant = kCompact_FontVariant;
  386. }
  387. if (currentFamily.fFonts.count() > 1 && currentFamily.fVariant != prevVariant) {
  388. SK_FONTCONFIGPARSER_WARNING("'%s' unexpected variant found\n"
  389. "Note: Every font file within a family must have identical variants.",
  390. value);
  391. }
  392. } else if (MEMEQ("lang", name, nameLen)) {
  393. SkLanguage currentLanguage = SkLanguage(value, valueLen);
  394. bool showWarning = false;
  395. if (currentFamily.fLanguages.empty()) {
  396. showWarning = (currentFamily.fFonts.count() > 1);
  397. currentFamily.fLanguages.push_back(std::move(currentLanguage));
  398. } else if (currentFamily.fLanguages[0] != currentLanguage) {
  399. showWarning = true;
  400. currentFamily.fLanguages[0] = std::move(currentLanguage);
  401. }
  402. if (showWarning) {
  403. SK_FONTCONFIGPARSER_WARNING("'%s' unexpected language found\n"
  404. "Note: Every font file within a family must have identical languages.",
  405. value);
  406. }
  407. } else if (MEMEQ("index", name, nameLen)) {
  408. if (!parse_non_negative_integer(value, &newFileInfo.fIndex)) {
  409. SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid index", value);
  410. }
  411. }
  412. }
  413. }
  414. self->fCurrentFontInfo = &newFileInfo;
  415. },
  416. /*end*/nullptr,
  417. /*tag*/nullptr,
  418. /*chars*/[](void* data, const char* s, int len) {
  419. FamilyData* self = static_cast<FamilyData*>(data);
  420. self->fCurrentFontInfo->fFileName.append(s, len);
  421. }
  422. };
  423. static const TagHandler fileSetHandler = {
  424. /*start*/nullptr,
  425. /*end*/nullptr,
  426. /*tag*/[](FamilyData* self, const char* tag, const char** attributes) -> const TagHandler* {
  427. size_t len = strlen(tag);
  428. if (MEMEQ("file", tag, len)) {
  429. return &fileHandler;
  430. }
  431. return nullptr;
  432. },
  433. /*chars*/nullptr,
  434. };
  435. static const TagHandler nameHandler = {
  436. /*start*/[](FamilyData* self, const char* tag, const char** attributes) {
  437. // The character data should be a name for the font.
  438. self->fCurrentFamily->fNames.push_back();
  439. },
  440. /*end*/nullptr,
  441. /*tag*/nullptr,
  442. /*chars*/[](void* data, const char* s, int len) {
  443. FamilyData* self = static_cast<FamilyData*>(data);
  444. SkAutoAsciiToLC tolc(s, len);
  445. self->fCurrentFamily->fNames.back().append(tolc.lc(), len);
  446. }
  447. };
  448. static const TagHandler nameSetHandler = {
  449. /*start*/nullptr,
  450. /*end*/nullptr,
  451. /*tag*/[](FamilyData* self, const char* tag, const char** attributes) -> const TagHandler* {
  452. size_t len = strlen(tag);
  453. if (MEMEQ("name", tag, len)) {
  454. return &nameHandler;
  455. }
  456. return nullptr;
  457. },
  458. /*chars*/nullptr,
  459. };
  460. static const TagHandler familyHandler = {
  461. /*start*/[](FamilyData* self, const char* tag, const char** attributes) {
  462. self->fCurrentFamily.reset(new FontFamily(self->fBasePath, self->fIsFallback));
  463. // 'order' (non-negative integer) [default -1]
  464. for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) {
  465. const char* value = attributes[i+1];
  466. parse_non_negative_integer(value, &self->fCurrentFamily->fOrder);
  467. }
  468. },
  469. /*end*/[](FamilyData* self, const char* tag) {
  470. *self->fFamilies.append() = self->fCurrentFamily.release();
  471. },
  472. /*tag*/[](FamilyData* self, const char* tag, const char** attributes) -> const TagHandler* {
  473. size_t len = strlen(tag);
  474. if (MEMEQ("nameset", tag, len)) {
  475. return &nameSetHandler;
  476. } else if (MEMEQ("fileset", tag, len)) {
  477. return &fileSetHandler;
  478. }
  479. return nullptr;
  480. },
  481. /*chars*/nullptr,
  482. };
  483. static const TagHandler familySetHandler = {
  484. /*start*/nullptr,
  485. /*end*/nullptr,
  486. /*tag*/[](FamilyData* self, const char* tag, const char** attributes) -> const TagHandler* {
  487. size_t len = strlen(tag);
  488. if (MEMEQ("family", tag, len)) {
  489. return &familyHandler;
  490. }
  491. return nullptr;
  492. },
  493. /*chars*/nullptr,
  494. };
  495. } // namespace jbParser
  496. static const TagHandler topLevelHandler = {
  497. /*start*/nullptr,
  498. /*end*/nullptr,
  499. /*tag*/[](FamilyData* self, const char* tag, const char** attributes) -> const TagHandler* {
  500. size_t len = strlen(tag);
  501. if (MEMEQ("familyset", tag, len)) {
  502. // 'version' (non-negative integer) [default 0]
  503. for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) {
  504. const char* name = attributes[i];
  505. size_t nameLen = strlen(name);
  506. if (MEMEQ("version", name, nameLen)) {
  507. const char* value = attributes[i+1];
  508. if (parse_non_negative_integer(value, &self->fVersion)) {
  509. if (self->fVersion >= 21) {
  510. return &lmpParser::familySetHandler;
  511. }
  512. }
  513. }
  514. }
  515. return &jbParser::familySetHandler;
  516. }
  517. return nullptr;
  518. },
  519. /*chars*/nullptr,
  520. };
  521. static void XMLCALL start_element_handler(void *data, const char *tag, const char **attributes) {
  522. FamilyData* self = static_cast<FamilyData*>(data);
  523. if (!self->fSkip) {
  524. const TagHandler* parent = self->fHandler.top();
  525. const TagHandler* child = parent->tag ? parent->tag(self, tag, attributes) : nullptr;
  526. if (child) {
  527. if (child->start) {
  528. child->start(self, tag, attributes);
  529. }
  530. self->fHandler.push_back(child);
  531. XML_SetCharacterDataHandler(self->fParser, child->chars);
  532. } else {
  533. SK_FONTCONFIGPARSER_WARNING("'%s' tag not recognized, skipping", tag);
  534. XML_SetCharacterDataHandler(self->fParser, nullptr);
  535. self->fSkip = self->fDepth;
  536. }
  537. }
  538. ++self->fDepth;
  539. }
  540. static void XMLCALL end_element_handler(void* data, const char* tag) {
  541. FamilyData* self = static_cast<FamilyData*>(data);
  542. --self->fDepth;
  543. if (!self->fSkip) {
  544. const TagHandler* child = self->fHandler.top();
  545. if (child->end) {
  546. child->end(self, tag);
  547. }
  548. self->fHandler.pop();
  549. const TagHandler* parent = self->fHandler.top();
  550. XML_SetCharacterDataHandler(self->fParser, parent->chars);
  551. }
  552. if (self->fSkip == self->fDepth) {
  553. self->fSkip = 0;
  554. const TagHandler* parent = self->fHandler.top();
  555. XML_SetCharacterDataHandler(self->fParser, parent->chars);
  556. }
  557. }
  558. static void XMLCALL xml_entity_decl_handler(void *data,
  559. const XML_Char *entityName,
  560. int is_parameter_entity,
  561. const XML_Char *value,
  562. int value_length,
  563. const XML_Char *base,
  564. const XML_Char *systemId,
  565. const XML_Char *publicId,
  566. const XML_Char *notationName)
  567. {
  568. FamilyData* self = static_cast<FamilyData*>(data);
  569. SK_FONTCONFIGPARSER_WARNING("'%s' entity declaration found, stopping processing", entityName);
  570. XML_StopParser(self->fParser, XML_FALSE);
  571. }
  572. static const XML_Memory_Handling_Suite sk_XML_alloc = {
  573. sk_malloc_throw,
  574. sk_realloc_throw,
  575. sk_free
  576. };
  577. /**
  578. * This function parses the given filename and stores the results in the given
  579. * families array. Returns the version of the file, negative if the file does not exist.
  580. */
  581. static int parse_config_file(const char* filename, SkTDArray<FontFamily*>& families,
  582. const SkString& basePath, bool isFallback)
  583. {
  584. SkFILEStream file(filename);
  585. // Some of the files we attempt to parse (in particular, /vendor/etc/fallback_fonts.xml)
  586. // are optional - failure here is okay because one of these optional files may not exist.
  587. if (!file.isValid()) {
  588. SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "'%s' could not be opened\n", filename);
  589. return -1;
  590. }
  591. SkAutoTCallVProc<skstd::remove_pointer_t<XML_Parser>, XML_ParserFree> parser(
  592. XML_ParserCreate_MM(nullptr, &sk_XML_alloc, nullptr));
  593. if (!parser) {
  594. SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "could not create XML parser\n");
  595. return -1;
  596. }
  597. FamilyData self(parser, families, basePath, isFallback, filename, &topLevelHandler);
  598. XML_SetUserData(parser, &self);
  599. // Disable entity processing, to inhibit internal entity expansion. See expat CVE-2013-0340
  600. XML_SetEntityDeclHandler(parser, xml_entity_decl_handler);
  601. // Start parsing oldschool; switch these in flight if we detect a newer version of the file.
  602. XML_SetElementHandler(parser, start_element_handler, end_element_handler);
  603. // One would assume it would be faster to have a buffer on the stack and call XML_Parse.
  604. // But XML_Parse will call XML_GetBuffer anyway and memmove the passed buffer into it.
  605. // (Unless XML_CONTEXT_BYTES is undefined, but all users define it.)
  606. // In debug, buffer a small odd number of bytes to detect slicing in XML_CharacterDataHandler.
  607. static const int bufferSize = 512 SkDEBUGCODE( - 507);
  608. bool done = false;
  609. while (!done) {
  610. void* buffer = XML_GetBuffer(parser, bufferSize);
  611. if (!buffer) {
  612. SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "could not buffer enough to continue\n");
  613. return -1;
  614. }
  615. size_t len = file.read(buffer, bufferSize);
  616. done = file.isAtEnd();
  617. XML_Status status = XML_ParseBuffer(parser, len, done);
  618. if (XML_STATUS_ERROR == status) {
  619. XML_Error error = XML_GetErrorCode(parser);
  620. int line = XML_GetCurrentLineNumber(parser);
  621. int column = XML_GetCurrentColumnNumber(parser);
  622. const XML_LChar* errorString = XML_ErrorString(error);
  623. SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "%s:%d:%d error %d: %s.\n",
  624. filename, line, column, error, errorString);
  625. return -1;
  626. }
  627. }
  628. return self.fVersion;
  629. }
  630. /** Returns the version of the system font file actually found, negative if none. */
  631. static int append_system_font_families(SkTDArray<FontFamily*>& fontFamilies,
  632. const SkString& basePath)
  633. {
  634. int initialCount = fontFamilies.count();
  635. int version = parse_config_file(LMP_SYSTEM_FONTS_FILE, fontFamilies, basePath, false);
  636. if (version < 0 || fontFamilies.count() == initialCount) {
  637. version = parse_config_file(OLD_SYSTEM_FONTS_FILE, fontFamilies, basePath, false);
  638. }
  639. return version;
  640. }
  641. /**
  642. * In some versions of Android prior to Android 4.2 (JellyBean MR1 at API
  643. * Level 17) the fallback fonts for certain locales were encoded in their own
  644. * XML files with a suffix that identified the locale. We search the provided
  645. * directory for those files,add all of their entries to the fallback chain, and
  646. * include the locale as part of each entry.
  647. */
  648. static void append_fallback_font_families_for_locale(SkTDArray<FontFamily*>& fallbackFonts,
  649. const char* dir,
  650. const SkString& basePath)
  651. {
  652. SkOSFile::Iter iter(dir, nullptr);
  653. SkString fileName;
  654. while (iter.next(&fileName, false)) {
  655. // The size of the prefix and suffix.
  656. static const size_t fixedLen = sizeof(LOCALE_FALLBACK_FONTS_PREFIX) - 1
  657. + sizeof(LOCALE_FALLBACK_FONTS_SUFFIX) - 1;
  658. // The size of the prefix, suffix, and a minimum valid language code
  659. static const size_t minSize = fixedLen + 2;
  660. if (fileName.size() < minSize ||
  661. !fileName.startsWith(LOCALE_FALLBACK_FONTS_PREFIX) ||
  662. !fileName.endsWith(LOCALE_FALLBACK_FONTS_SUFFIX))
  663. {
  664. continue;
  665. }
  666. SkString locale(fileName.c_str() + sizeof(LOCALE_FALLBACK_FONTS_PREFIX) - 1,
  667. fileName.size() - fixedLen);
  668. SkString absoluteFilename;
  669. absoluteFilename.printf("%s/%s", dir, fileName.c_str());
  670. SkTDArray<FontFamily*> langSpecificFonts;
  671. parse_config_file(absoluteFilename.c_str(), langSpecificFonts, basePath, true);
  672. for (int i = 0; i < langSpecificFonts.count(); ++i) {
  673. FontFamily* family = langSpecificFonts[i];
  674. family->fLanguages.emplace_back(locale);
  675. *fallbackFonts.append() = family;
  676. }
  677. }
  678. }
  679. static void append_system_fallback_font_families(SkTDArray<FontFamily*>& fallbackFonts,
  680. const SkString& basePath)
  681. {
  682. parse_config_file(FALLBACK_FONTS_FILE, fallbackFonts, basePath, true);
  683. append_fallback_font_families_for_locale(fallbackFonts,
  684. LOCALE_FALLBACK_FONTS_SYSTEM_DIR,
  685. basePath);
  686. }
  687. static void mixin_vendor_fallback_font_families(SkTDArray<FontFamily*>& fallbackFonts,
  688. const SkString& basePath)
  689. {
  690. SkTDArray<FontFamily*> vendorFonts;
  691. parse_config_file(VENDOR_FONTS_FILE, vendorFonts, basePath, true);
  692. append_fallback_font_families_for_locale(vendorFonts,
  693. LOCALE_FALLBACK_FONTS_VENDOR_DIR,
  694. basePath);
  695. // This loop inserts the vendor fallback fonts in the correct order in the
  696. // overall fallbacks list.
  697. int currentOrder = -1;
  698. for (int i = 0; i < vendorFonts.count(); ++i) {
  699. FontFamily* family = vendorFonts[i];
  700. int order = family->fOrder;
  701. if (order < 0) {
  702. if (currentOrder < 0) {
  703. // Default case - just add it to the end of the fallback list
  704. *fallbackFonts.append() = family;
  705. } else {
  706. // no order specified on this font, but we're incrementing the order
  707. // based on an earlier order insertion request
  708. *fallbackFonts.insert(currentOrder++) = family;
  709. }
  710. } else {
  711. // Add the font into the fallback list in the specified order. Set
  712. // currentOrder for correct placement of other fonts in the vendor list.
  713. *fallbackFonts.insert(order) = family;
  714. currentOrder = order + 1;
  715. }
  716. }
  717. }
  718. void SkFontMgr_Android_Parser::GetSystemFontFamilies(SkTDArray<FontFamily*>& fontFamilies) {
  719. // Version 21 of the system font configuration does not need any fallback configuration files.
  720. SkString basePath(getenv("ANDROID_ROOT"));
  721. basePath.append(SK_FONT_FILE_PREFIX, sizeof(SK_FONT_FILE_PREFIX) - 1);
  722. if (append_system_font_families(fontFamilies, basePath) >= 21) {
  723. return;
  724. }
  725. // Append all the fallback fonts to system fonts
  726. SkTDArray<FontFamily*> fallbackFonts;
  727. append_system_fallback_font_families(fallbackFonts, basePath);
  728. mixin_vendor_fallback_font_families(fallbackFonts, basePath);
  729. fontFamilies.append(fallbackFonts.count(), fallbackFonts.begin());
  730. }
  731. void SkFontMgr_Android_Parser::GetCustomFontFamilies(SkTDArray<FontFamily*>& fontFamilies,
  732. const SkString& basePath,
  733. const char* fontsXml,
  734. const char* fallbackFontsXml,
  735. const char* langFallbackFontsDir)
  736. {
  737. if (fontsXml) {
  738. parse_config_file(fontsXml, fontFamilies, basePath, false);
  739. }
  740. if (fallbackFontsXml) {
  741. parse_config_file(fallbackFontsXml, fontFamilies, basePath, true);
  742. }
  743. if (langFallbackFontsDir) {
  744. append_fallback_font_families_for_locale(fontFamilies,
  745. langFallbackFontsDir,
  746. basePath);
  747. }
  748. }
  749. SkLanguage SkLanguage::getParent() const {
  750. SkASSERT(!fTag.isEmpty());
  751. const char* tag = fTag.c_str();
  752. // strip off the rightmost "-.*"
  753. const char* parentTagEnd = strrchr(tag, '-');
  754. if (parentTagEnd == nullptr) {
  755. return SkLanguage();
  756. }
  757. size_t parentTagLen = parentTagEnd - tag;
  758. return SkLanguage(tag, parentTagLen);
  759. }