30#define LMP_SYSTEM_FONTS_FILE "/system/etc/fonts.xml"
31#define OLD_SYSTEM_FONTS_FILE "/system/etc/system_fonts.xml"
32#define FALLBACK_FONTS_FILE "/system/etc/fallback_fonts.xml"
33#define VENDOR_FONTS_FILE "/vendor/etc/fallback_fonts.xml"
35#define LOCALE_FALLBACK_FONTS_SYSTEM_DIR "/system/etc"
36#define LOCALE_FALLBACK_FONTS_VENDOR_DIR "/vendor/etc"
37#define LOCALE_FALLBACK_FONTS_PREFIX "fallback_fonts-"
38#define LOCALE_FALLBACK_FONTS_SUFFIX ".xml"
40#ifndef SK_FONT_FILE_PREFIX
41# define SK_FONT_FILE_PREFIX "/fonts/"
93 const SkString& basePath,
bool isFallback,
const char* filename,
122static bool memeq(
const char* s1,
const char* s2,
size_t n1,
size_t n2) {
123 return n1 == n2 && 0 == memcmp(s1, s2, n1);
125#define MEMEQ(c, s, n) memeq(c, s, sizeof(c) - 1, n)
127#define ATTS_NON_NULL(a, i) (a[i] != nullptr && a[i+1] != nullptr)
129#define SK_FONTMGR_ANDROID_PARSER_PREFIX "[SkFontMgr Android Parser] "
131#define SK_FONTCONFIGPARSER_WARNING(message, ...) \
132 SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "%s:%d:%d: warning: " message "\n", \
134 (int)XML_GetCurrentLineNumber(self->fParser), \
135 (int)XML_GetCurrentColumnNumber(self->fParser), \
139 return c ==
' ' || c ==
'\n'|| c ==
'\r' || c ==
'\t';
143 char* str =
s->data();
144 const char*
start = str;
153 memmove(str,
start, len);
163 if (i == valueLen) {
break; }
168 if (i == valueLen) {
break; }
179 bool axisTagIsValid =
false;
180 bool axisStyleValueIsValid =
false;
182 const char*
name = attributes[i];
183 const char*
value = attributes[i+1];
184 size_t nameLen = strlen(
name);
186 size_t valueLen = strlen(
value);
189 axisTagIsValid =
true;
190 for (
int j = 0; j < file.fVariationDesignPosition.size() - 1; ++j) {
191 if (file.fVariationDesignPosition[j].axis == axisTag) {
192 axisTagIsValid =
false;
194 (
char)((axisTag >> 24) & 0xFF),
195 (
char)((axisTag >> 16) & 0xFF),
196 (
char)((axisTag >> 8) & 0xFF),
197 (
char)((axisTag ) & 0xFF));
203 }
else if (
MEMEQ(
"stylevalue",
name, nameLen)) {
204 if (parse_fixed<16>(
value, &axisStyleValue)) {
205 axisStyleValueIsValid =
true;
211 if (axisTagIsValid && axisStyleValueIsValid) {
212 auto& coordinate = file.fVariationDesignPosition.push_back();
213 coordinate.axis = axisTag;
229 self->fCurrentFontInfo = &file;
232 const char*
name = attributes[i];
233 const char*
value = attributes[i+1];
234 size_t nameLen = strlen(
name);
239 }
else if (
MEMEQ(
"style",
name, nameLen)) {
240 size_t valueLen = strlen(
value);
243 }
else if (
MEMEQ(
"italic",
value, valueLen)) {
246 }
else if (
MEMEQ(
"index",
name, nameLen)) {
250 }
else if (
MEMEQ(
"fallbackFor",
name, nameLen)) {
256 std::unique_ptr<FontFamily>* fallbackFamily =
257 self->fCurrentFamily->fallbackFamilies.find(fallbackFor);
258 if (!fallbackFamily) {
259 std::unique_ptr<FontFamily> newFallbackFamily(
261 fallbackFamily =
self->fCurrentFamily->fallbackFamilies.set(
262 fallbackFor, std::move(newFallbackFamily));
263 (*fallbackFamily)->fLanguages =
self->fCurrentFamily->fLanguages;
264 (*fallbackFamily)->fVariant =
self->fCurrentFamily->fVariant;
265 (*fallbackFamily)->fOrder =
self->fCurrentFamily->fOrder;
266 (*fallbackFamily)->fFallbackFor = fallbackFor;
268 self->fCurrentFontInfo = &(*fallbackFamily)->fFonts.emplace_back(file);
269 self->fCurrentFamily->fFonts.pop_back();
276 size_t len = strlen(tag);
277 if (
MEMEQ(
"axis", tag, len)) {
282 [](
void* data,
const char*
s,
int len) {
295 self->fCurrentFamily.reset(family);
297 const char*
name = attributes[i];
298 const char*
value = attributes[i+1];
299 size_t nameLen = strlen(
name);
300 size_t valueLen = strlen(
value);
305 }
else if (
MEMEQ(
"lang",
name, nameLen)) {
307 }
else if (
MEMEQ(
"variant",
name, nameLen)) {
310 }
else if (
MEMEQ(
"compact",
value, valueLen)) {
317 *
self->fFamilies.append() =
self->fCurrentFamily.release();
320 size_t len = strlen(tag);
321 if (
MEMEQ(
"font", tag, len)) {
330 for (
int i = 0; i <
self->fFamilies.size(); i++) {
332 for (
int j = 0; j < candidate->
fNames.
size(); j++) {
333 if (candidate->
fNames[j] == familyName) {
354 const char*
name = attributes[i];
355 const char*
value = attributes[i+1];
356 size_t nameLen = strlen(
name);
359 aliasName.
set(tolc.
lc());
362 }
else if (
MEMEQ(
"weight",
name, nameLen)) {
380 for (
int i = 0; i < targetFamily->
fFonts.
size(); i++) {
381 if (targetFamily->
fFonts[i].fWeight == weight) {
385 *
self->fFamilies.append() = family;
396 [](
FamilyData*
self,
const char* tag,
const char** attributes) { },
399 size_t len = strlen(tag);
400 if (
MEMEQ(
"family", tag, len)) {
402 }
else if (
MEMEQ(
"alias", tag, len)) {
424 const char*
name = attributes[i];
425 const char*
value = attributes[i+1];
426 size_t nameLen = strlen(
name);
427 size_t valueLen = strlen(
value);
432 }
else if (
MEMEQ(
"compact",
value, valueLen)) {
437 "Note: Every font file within a family must have identical variants.",
441 }
else if (
MEMEQ(
"lang",
name, nameLen)) {
443 bool showWarning =
false;
445 showWarning = (currentFamily.
fFonts.
size() > 1);
447 }
else if (currentFamily.
fLanguages[0] != currentLanguage) {
449 currentFamily.
fLanguages[0] = std::move(currentLanguage);
453 "Note: Every font file within a family must have identical languages.",
457 }
else if (
MEMEQ(
"index",
name, nameLen)) {
464 self->fCurrentFontInfo = &newFileInfo;
468 [](
void* data,
const char*
s,
int len) {
478 size_t len = strlen(tag);
479 if (
MEMEQ(
"file", tag, len)) {
490 self->fCurrentFamily->fNames.push_back();
494 [](
void* data,
const char*
s,
int len) {
497 self->fCurrentFamily->fNames.back().append(tolc.
lc(), len);
505 size_t len = strlen(tag);
506 if (
MEMEQ(
"name", tag, len)) {
516 self->fCurrentFamily = std::make_unique<FontFamily>(
self->fBasePath,
self->fIsFallback);
519 const char*
value = attributes[i+1];
524 *
self->fFamilies.append() =
self->fCurrentFamily.release();
527 size_t len = strlen(tag);
528 if (
MEMEQ(
"nameset", tag, len)) {
530 }
else if (
MEMEQ(
"fileset", tag, len)) {
542 size_t len = strlen(tag);
543 if (
MEMEQ(
"family", tag, len)) {
557 size_t len = strlen(tag);
558 if (
MEMEQ(
"familyset", tag, len)) {
561 const char*
name = attributes[i];
562 size_t nameLen = strlen(
name);
564 const char*
value = attributes[i+1];
566 if (
self->fVersion >= 21) {
589 self->fHandler.push_back(child);
590 XML_SetCharacterDataHandler(
self->fParser, child->
chars);
593 XML_SetCharacterDataHandler(
self->fParser,
nullptr);
610 self->fHandler.pop_back();
612 XML_SetCharacterDataHandler(
self->fParser, parent->
chars);
618 XML_SetCharacterDataHandler(
self->fParser, parent->
chars);
623 const XML_Char *entityName,
624 int is_parameter_entity,
625 const XML_Char *value,
627 const XML_Char *
base,
628 const XML_Char *systemId,
629 const XML_Char *publicId,
630 const XML_Char *notationName)
634 XML_StopParser(
self->fParser, XML_FALSE);
648 const SkString& basePath,
bool isFallback)
654 if (!file.isValid()) {
667 XML_SetUserData(parser, &
self);
679 static const int bufferSize = 512
SkDEBUGCODE( - 507);
682 void*
buffer = XML_GetBuffer(parser, bufferSize);
687 size_t len = file.read(
buffer, bufferSize);
688 done = file.isAtEnd();
689 XML_Status status = XML_ParseBuffer(parser, len,
done);
690 if (XML_STATUS_ERROR == status) {
691 XML_Error
error = XML_GetErrorCode(parser);
692 int line = XML_GetCurrentLineNumber(parser);
693 int column = XML_GetCurrentColumnNumber(parser);
694 const XML_LChar* errorString = XML_ErrorString(
error);
696 filename, line, column,
error, errorString);
700 return self.fVersion;
707 int initialCount = fontFamilies.
size();
709 if (version < 0 || fontFamilies.
size() == initialCount) {
728 while (iter.
next(&fileName,
false)) {
734 static const size_t minSize = fixedLen + 2;
736 if (fileName.
size() < minSize ||
744 fileName.
size() - fixedLen);
747 absoluteFilename.
printf(
"%s/%s", dir, fileName.
c_str());
752 for (
int i = 0; i < langSpecificFonts.
size(); ++i) {
755 *fallbackFonts.
append() = family;
780 int currentOrder = -1;
781 for (
int i = 0; i < vendorFonts.
size(); ++i) {
783 int order = family->
fOrder;
785 if (currentOrder < 0) {
787 *fallbackFonts.
append() = family;
791 *fallbackFonts.
insert(currentOrder++) = family;
796 *fallbackFonts.
insert(order) = family;
797 currentOrder = order + 1;
804 SkString basePath(getenv(
"ANDROID_ROOT"));
820 const char* fontsXml,
821 const char* fallbackFontsXml,
822 const char* langFallbackFontsDir)
827 if (fallbackFontsXml) {
830 if (langFallbackFontsDir) {
832 langFallbackFontsDir,
839 const char* tag = fTag.
c_str();
842 const char* parentTagEnd = strrchr(tag,
'-');
843 if (parentTagEnd ==
nullptr) {
846 size_t parentTagLen = parentTagEnd - tag;
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define SkFixedToScalar(x)
#define LOCALE_FALLBACK_FONTS_VENDOR_DIR
static void append_fallback_font_families_for_locale(SkTDArray< FontFamily * > &fallbackFonts, const char *dir, const SkString &basePath)
#define ATTS_NON_NULL(a, i)
static void XMLCALL start_element_handler(void *data, const char *tag, const char **attributes)
static void XMLCALL end_element_handler(void *data, const char *tag)
static void XMLCALL xml_entity_decl_handler(void *data, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName)
#define VENDOR_FONTS_FILE
static bool memeq(const char *s1, const char *s2, size_t n1, size_t n2)
static const TagHandler topLevelHandler
#define FALLBACK_FONTS_FILE
#define OLD_SYSTEM_FONTS_FILE
static int parse_config_file(const char *filename, SkTDArray< FontFamily * > &families, const SkString &basePath, bool isFallback)
static void mixin_vendor_fallback_font_families(SkTDArray< FontFamily * > &fallbackFonts, const SkString &basePath)
static void append_system_fallback_font_families(SkTDArray< FontFamily * > &fallbackFonts, const SkString &basePath)
static void trim_string(SkString *s)
static bool is_whitespace(char c)
static const XML_Memory_Handling_Suite sk_XML_alloc
static void parse_space_separated_languages(const char *value, size_t valueLen, TArray< SkLanguage, true > &languages)
#define SK_FONTCONFIGPARSER_WARNING(message,...)
#define SK_FONT_FILE_PREFIX
#define LOCALE_FALLBACK_FONTS_SUFFIX
#define SK_FONTMGR_ANDROID_PARSER_PREFIX
#define LOCALE_FALLBACK_FONTS_PREFIX
#define LMP_SYSTEM_FONTS_FILE
#define LOCALE_FALLBACK_FONTS_SYSTEM_DIR
static int append_system_font_families(SkTDArray< FontFamily * > &fontFamilies, const SkString &basePath)
bool parse_non_negative_integer(const char *s, T *value)
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
SK_API void * sk_realloc_throw(void *buffer, size_t size)
static constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d)
SkLanguage getParent() const
SK_SPI bool next(SkString *name, bool getDir=false)
bool startsWith(const char prefixStr[]) const
void printf(const char format[],...) SK_PRINTF_LIKE(2
void set(const SkString &src)
void append(const char text[])
bool endsWith(const char suffixStr[]) const
const char * c_str() const
T & emplace_back(Args &&... args)
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
void GetCustomFontFamilies(SkTDArray< FontFamily * > &fontFamilies, const SkString &basePath, const char *fontsXml, const char *fallbackFontsXml, const char *langFallbackFontsDir=nullptr)
void GetSystemFontFamilies(SkTDArray< FontFamily * > &fontFamilies)
static const TagHandler nameSetHandler
static const TagHandler fileSetHandler
static const TagHandler fileHandler
static const TagHandler nameHandler
static const TagHandler familyHandler
static const TagHandler familySetHandler
static FontFamily * find_family(FamilyData *self, const SkString &familyName)
static const TagHandler aliasHandler
static const TagHandler axisHandler
static const TagHandler fontHandler
static const TagHandler familySetHandler
static const TagHandler familyHandler
std::unique_ptr< FontFamily > fCurrentFamily
SkTDArray< const TagHandler * > fHandler
SkTDArray< FontFamily * > & fFamilies
const SkString & fBasePath
FontFileInfo * fCurrentFontInfo
FamilyData(XML_Parser parser, SkTDArray< FontFamily * > &families, const SkString &basePath, bool isFallback, const char *filename, const TagHandler *topLevelHandler)
skia_private::TArray< SkString, true > fNames
skia_private::TArray< SkLanguage, true > fLanguages
skia_private::TArray< FontFileInfo, true > fFonts
const TagHandler *(* tag)(FamilyData *data, const char *tag, const char **attributes)
void(* start)(FamilyData *data, const char *tag, const char **attributes)
XML_CharacterDataHandler chars
void(* end)(FamilyData *data, const char *tag)