Index: src/ports/SkFontConfigParser_android.cpp |
diff --git a/src/ports/SkFontConfigParser_android.cpp b/src/ports/SkFontConfigParser_android.cpp |
index 2e9054d36d62527eab17a5497f0b1a7c9b48eb0f..90450a99408ab008b4a0c8c7a0081f4dd1bb81ae 100644 |
--- a/src/ports/SkFontConfigParser_android.cpp |
+++ b/src/ports/SkFontConfigParser_android.cpp |
@@ -16,8 +16,6 @@ |
#include <limits> |
- |
- |
// From Android version LMP onwards, all font files collapse into |
// /system/etc/fonts.xml. Instead of trying to detect which version |
// we're on, try to open fonts.xml; if that fails, fall back to the |
@@ -51,23 +49,25 @@ |
* can read these variables that are relevant to the current parsing. |
*/ |
struct FamilyData { |
- FamilyData(XML_Parser parser, SkTDArray<FontFamily*> &families) |
+ FamilyData(XML_Parser parser, SkTDArray<FontFamily*>& families) |
: fParser(parser) |
, fFamilies(families) |
, fCurrentFamily(NULL) |
, fCurrentFontInfo(NULL) |
, fCurrentTag(NO_TAG) |
- { }; |
+ , fVersion(0) |
+ { } |
XML_Parser fParser; // The expat parser doing the work, owned by caller |
SkTDArray<FontFamily*>& fFamilies; // The array to append families, owned by caller |
SkAutoTDelete<FontFamily> fCurrentFamily; // The family being created, owned by this |
FontFileInfo* fCurrentFontInfo; // The fontInfo being created, owned by currentFamily |
int fCurrentTag; // Flag to indicate when we're in nameset/fileset tags |
+ int fVersion; // The version of the file parsed. |
}; |
/** http://www.w3.org/TR/html-markup/datatypes.html#common.data.integer.non-negative-def */ |
-template <typename T> static bool parseNonNegativeInteger(const char* s, T* value) { |
+template <typename T> static bool parse_non_negative_integer(const char* s, T* value) { |
SK_COMPILE_ASSERT(std::numeric_limits<T>::is_integer, T_must_be_integer); |
const T nMax = std::numeric_limits<T>::max() / 10; |
const T dMax = std::numeric_limits<T>::max() - (nMax * 10); |
@@ -133,7 +133,7 @@ void fontElementHandler(XML_Parser parser, FontFileInfo* file, const char** attr |
const char* value = attributes[i+1]; |
size_t nameLen = strlen(name); |
if (nameLen == 6 && !strncmp("weight", name, nameLen)) { |
- if (!parseNonNegativeInteger(value, &file->fWeight)) { |
+ if (!parse_non_negative_integer(value, &file->fWeight)) { |
SkDebugf("---- Font weight %s (INVALID)", value); |
file->fWeight = 0; |
} |
@@ -178,7 +178,7 @@ void aliasElementHandler(FamilyData* familyData, const char** attributes) { |
} else if (nameLen == 2 && !strncmp("to", name, nameLen)) { |
to.set(value); |
} else if (nameLen == 6 && !strncmp("weight", name, nameLen)) { |
- parseNonNegativeInteger(value, &weight); |
+ parse_non_negative_integer(value, &weight); |
} |
} |
@@ -237,7 +237,7 @@ namespace jbParser { |
* Handler for arbitrary text. This is used to parse the text inside each name |
* or file tag. The resulting strings are put into the fNames or FontFileInfo arrays. |
*/ |
-static void textHandler(void* data, const char* s, int len) { |
+static void text_handler(void* data, const char* s, int len) { |
FamilyData* familyData = (FamilyData*) data; |
// Make sure we're in the right state to store this name information |
if (familyData->fCurrentFamily.get() && |
@@ -264,7 +264,7 @@ static void textHandler(void* data, const char* s, int len) { |
* Handler for font files. This processes the attributes for language and |
* variants then lets textHandler handle the actual file name |
*/ |
-static void fontFileElementHandler(FamilyData* familyData, const char** attributes) { |
+static void font_file_element_handler(FamilyData* familyData, const char** attributes) { |
FontFileInfo& newFileInfo = familyData->fCurrentFamily->fFonts.push_back(); |
if (attributes) { |
size_t currentAttributeIndex = 0; |
@@ -298,7 +298,7 @@ static void fontFileElementHandler(FamilyData* familyData, const char** attribut |
} |
} else if (nameLength == 5 && strncmp(attributeName, "index", nameLength) == 0) { |
int value; |
- if (parseNonNegativeInteger(attributeValue, &value)) { |
+ if (parse_non_negative_integer(attributeValue, &value)) { |
newFileInfo.fIndex = value; |
} else { |
SkDebugf("---- SystemFonts index=%s (INVALID)", attributeValue); |
@@ -309,14 +309,14 @@ static void fontFileElementHandler(FamilyData* familyData, const char** attribut |
} |
} |
familyData->fCurrentFontInfo = &newFileInfo; |
- XML_SetCharacterDataHandler(familyData->fParser, textHandler); |
+ XML_SetCharacterDataHandler(familyData->fParser, text_handler); |
} |
/** |
* Handler for the start of a tag. The only tags we expect are familyset, family, |
* nameset, fileset, name, and file. |
*/ |
-static void startElementHandler(void* data, const char* tag, const char** atts) { |
+static void start_element_handler(void* data, const char* tag, const char** atts) { |
FamilyData* familyData = (FamilyData*) data; |
size_t len = strlen(tag); |
if (len == 9 && strncmp(tag, "familyset", len) == 0) { |
@@ -327,10 +327,11 @@ static void startElementHandler(void* data, const char* tag, const char** atts) |
if (nameLen == 7 && strncmp(atts[i], "version", nameLen)) continue; |
const char* valueString = atts[i+1]; |
int version; |
- if (parseNonNegativeInteger(valueString, &version) && (version >= 21)) { |
+ if (parse_non_negative_integer(valueString, &version) && (version >= 21)) { |
XML_SetElementHandler(familyData->fParser, |
lmpParser::startElementHandler, |
lmpParser::endElementHandler); |
+ familyData->fVersion = version; |
} |
} |
} else if (len == 6 && strncmp(tag, "family", len) == 0) { |
@@ -341,7 +342,7 @@ static void startElementHandler(void* data, const char* tag, const char** atts) |
atts[i+1] != NULL; i += 2) { |
const char* valueString = atts[i+1]; |
int value; |
- if (parseNonNegativeInteger(valueString, &value)) { |
+ if (parse_non_negative_integer(valueString, &value)) { |
familyData->fCurrentFamily->fOrder = value; |
} |
} |
@@ -351,10 +352,10 @@ static void startElementHandler(void* data, const char* tag, const char** atts) |
familyData->fCurrentTag = FILESET_TAG; |
} else if (len == 4 && strncmp(tag, "name", len) == 0 && familyData->fCurrentTag == NAMESET_TAG) { |
// If it's a Name, parse the text inside |
- XML_SetCharacterDataHandler(familyData->fParser, textHandler); |
+ XML_SetCharacterDataHandler(familyData->fParser, text_handler); |
} else if (len == 4 && strncmp(tag, "file", len) == 0 && familyData->fCurrentTag == FILESET_TAG) { |
// If it's a file, parse the attributes, then parse the text inside |
- fontFileElementHandler(familyData, atts); |
+ font_file_element_handler(familyData, atts); |
} |
} |
@@ -362,7 +363,7 @@ static void startElementHandler(void* data, const char* tag, const char** atts) |
* Handler for the end of tags. We only care about family, nameset, fileset, |
* name, and file. |
*/ |
-static void endElementHandler(void* data, const char* tag) { |
+static void end_element_handler(void* data, const char* tag) { |
FamilyData* familyData = (FamilyData*) data; |
size_t len = strlen(tag); |
if (len == 6 && strncmp(tag, "family", len)== 0) { |
@@ -387,23 +388,23 @@ static void endElementHandler(void* data, const char* tag) { |
/** |
* This function parses the given filename and stores the results in the given |
- * families array. |
+ * families array. Returns the version of the file, negative if the file does not exist. |
*/ |
-static void parseConfigFile(const char* filename, SkTDArray<FontFamily*> &families) { |
+static int parse_config_file(const char* filename, SkTDArray<FontFamily*>& families) { |
FILE* file = fopen(filename, "r"); |
// Some of the files we attempt to parse (in particular, /vendor/etc/fallback_fonts.xml) |
// are optional - failure here is okay because one of these optional files may not exist. |
if (NULL == file) { |
- return; |
+ return -1; |
} |
XML_Parser parser = XML_ParserCreate(NULL); |
FamilyData familyData(parser, families); |
XML_SetUserData(parser, &familyData); |
// Start parsing oldschool; switch these in flight if we detect a newer version of the file. |
- XML_SetElementHandler(parser, jbParser::startElementHandler, jbParser::endElementHandler); |
+ XML_SetElementHandler(parser, jbParser::start_element_handler, jbParser::end_element_handler); |
char buffer[512]; |
bool done = false; |
@@ -417,15 +418,17 @@ static void parseConfigFile(const char* filename, SkTDArray<FontFamily*> &famili |
} |
XML_ParserFree(parser); |
fclose(file); |
+ return familyData.fVersion; |
} |
-static void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { |
+/** Returns the version of the system font file actually found, negative if none. */ |
+static int append_system_font_families(SkTDArray<FontFamily*>& fontFamilies) { |
int initialCount = fontFamilies.count(); |
- parseConfigFile(LMP_SYSTEM_FONTS_FILE, fontFamilies); |
- |
- if (initialCount == fontFamilies.count()) { |
- parseConfigFile(OLD_SYSTEM_FONTS_FILE, fontFamilies); |
+ int version = parse_config_file(LMP_SYSTEM_FONTS_FILE, fontFamilies); |
+ if (version < 0 || fontFamilies.count() == initialCount) { |
+ version = parse_config_file(OLD_SYSTEM_FONTS_FILE, fontFamilies); |
} |
+ return version; |
} |
/** |
@@ -435,7 +438,9 @@ static void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { |
* directory for those files,add all of their entries to the fallback chain, and |
* include the locale as part of each entry. |
*/ |
-static void getFallbackFontFamiliesForLocale(SkTDArray<FontFamily*> &fallbackFonts, const char* dir) { |
+static void append_fallback_font_families_for_locale(SkTDArray<FontFamily*>& fallbackFonts, |
+ const char* dir) |
+{ |
#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) |
// The framework is beyond Android 4.2 and can therefore skip this function |
return; |
@@ -465,7 +470,7 @@ static void getFallbackFontFamiliesForLocale(SkTDArray<FontFamily*> &fallbackFon |
absoluteFilename.printf("%s/%s", dir, fileName.c_str()); |
SkTDArray<FontFamily*> langSpecificFonts; |
- parseConfigFile(absoluteFilename.c_str(), langSpecificFonts); |
+ parse_config_file(absoluteFilename.c_str(), langSpecificFonts); |
for (int i = 0; i < langSpecificFonts.count(); ++i) { |
FontFamily* family = langSpecificFonts[i]; |
@@ -482,13 +487,15 @@ static void getFallbackFontFamiliesForLocale(SkTDArray<FontFamily*> &fallbackFon |
} |
} |
-static void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) { |
- SkTDArray<FontFamily*> vendorFonts; |
- parseConfigFile(FALLBACK_FONTS_FILE, fallbackFonts); |
- parseConfigFile(VENDOR_FONTS_FILE, vendorFonts); |
+static void append_system_fallback_font_families(SkTDArray<FontFamily*>& fallbackFonts) { |
+ parse_config_file(FALLBACK_FONTS_FILE, fallbackFonts); |
+ append_fallback_font_families_for_locale(fallbackFonts, LOCALE_FALLBACK_FONTS_SYSTEM_DIR); |
+} |
- getFallbackFontFamiliesForLocale(fallbackFonts, LOCALE_FALLBACK_FONTS_SYSTEM_DIR); |
- getFallbackFontFamiliesForLocale(vendorFonts, LOCALE_FALLBACK_FONTS_VENDOR_DIR); |
+static void mixin_vendor_fallback_font_families(SkTDArray<FontFamily*>& fallbackFonts) { |
+ SkTDArray<FontFamily*> vendorFonts; |
+ parse_config_file(VENDOR_FONTS_FILE, vendorFonts); |
+ append_fallback_font_families_for_locale(vendorFonts, LOCALE_FALLBACK_FONTS_VENDOR_DIR); |
// This loop inserts the vendor fallback fonts in the correct order in the |
// overall fallbacks list. |
@@ -518,27 +525,30 @@ static void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) { |
* Loads data on font families from various expected configuration files. The |
* resulting data is returned in the given fontFamilies array. |
*/ |
-void SkFontConfigParser::GetFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { |
- |
- getSystemFontFamilies(fontFamilies); |
+void SkFontConfigParser::GetFontFamilies(SkTDArray<FontFamily*>& fontFamilies) { |
+ // Version 21 of the system font configuration does not need any fallback configuration files. |
+ if (append_system_font_families(fontFamilies) >= 21) { |
+ return; |
+ } |
// Append all the fallback fonts to system fonts |
SkTDArray<FontFamily*> fallbackFonts; |
- getFallbackFontFamilies(fallbackFonts); |
+ append_system_fallback_font_families(fallbackFonts); |
+ mixin_vendor_fallback_font_families(fallbackFonts); |
for (int i = 0; i < fallbackFonts.count(); ++i) { |
fallbackFonts[i]->fIsFallbackFont = true; |
*fontFamilies.append() = fallbackFonts[i]; |
} |
} |
-void SkFontConfigParser::GetTestFontFamilies(SkTDArray<FontFamily*> &fontFamilies, |
+void SkFontConfigParser::GetTestFontFamilies(SkTDArray<FontFamily*>& fontFamilies, |
const char* testMainConfigFile, |
const char* testFallbackConfigFile) { |
- parseConfigFile(testMainConfigFile, fontFamilies); |
+ parse_config_file(testMainConfigFile, fontFamilies); |
SkTDArray<FontFamily*> fallbackFonts; |
if (testFallbackConfigFile) { |
- parseConfigFile(testFallbackConfigFile, fallbackFonts); |
+ parse_config_file(testFallbackConfigFile, fallbackFonts); |
} |
// Append all fallback fonts to system fonts |