Index: src/ports/SkFontConfigParser_android.cpp |
diff --git a/src/ports/FontHostConfiguration_android.cpp b/src/ports/SkFontConfigParser_android.cpp |
similarity index 64% |
copy from src/ports/FontHostConfiguration_android.cpp |
copy to src/ports/SkFontConfigParser_android.cpp |
index ef5a742a18ab90eb22108be000d3d2641f1fef36..9214d1bf61484e8addc8198ca4753d840c61c234 100644 |
--- a/src/ports/FontHostConfiguration_android.cpp |
+++ b/src/ports/SkFontConfigParser_android.cpp |
@@ -5,9 +5,10 @@ |
* found in the LICENSE file. |
*/ |
-#include "FontHostConfiguration_android.h" |
-#include "SkString.h" |
+#include "SkFontConfigParser_android.h" |
#include "SkTDArray.h" |
+#include "SkTypeface.h" |
+ |
#include <expat.h> |
#include <sys/system_properties.h> |
@@ -15,7 +16,6 @@ |
#define FALLBACK_FONTS_FILE "/system/etc/fallback_fonts.xml" |
#define VENDOR_FONTS_FILE "/vendor/etc/fallback_fonts.xml" |
- |
// These defines are used to determine the kind of tag that we're currently |
// populating with data. We only care about the sibling tags nameset and fileset |
// for now. |
@@ -28,24 +28,25 @@ |
* can read these variables that are relevant to the current parsing. |
*/ |
struct FamilyData { |
- FamilyData(XML_Parser *parserRef, SkTDArray<FontFamily*> &familiesRef, const AndroidLocale &localeRef) : |
- parser(parserRef), families(familiesRef), currentTag(NO_TAG), |
- locale(localeRef), currentFamilyLangMatch(false), familyLangMatchCount(0) {} |
+ FamilyData(XML_Parser *parserRef, SkTDArray<FontFamily*> &familiesRef) : |
+ parser(parserRef), |
+ families(familiesRef), |
+ currentFamily(NULL), |
+ currentFontInfo(NULL), |
+ currentTag(NO_TAG) {}; |
XML_Parser *parser; // The expat parser doing the work |
SkTDArray<FontFamily*> &families; // The array that each family is put into as it is parsed |
FontFamily *currentFamily; // The current family being created |
+ FontFileInfo *currentFontInfo; // The current fontInfo being created |
int currentTag; // A flag to indicate whether we're in nameset/fileset tags |
- const AndroidLocale &locale; // The locale to which we compare the "lang" attribute of File. |
- bool currentFamilyLangMatch; // If currentFamily's File has a "lang" attribute and matches locale. |
- int familyLangMatchCount; // Number of families containing File which has a "lang" attribute and matches locale. |
}; |
/** |
* 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 fFileNames arrays. |
+ * or file tag. The resulting strings are put into the fNames or FontFileInfo arrays. |
*/ |
-void textHandler(void *data, const char *s, int len) { |
+static void textHandler(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->currentFamily && |
@@ -60,7 +61,9 @@ void textHandler(void *data, const char *s, int len) { |
*(familyData->currentFamily->fNames.append()) = buff; |
break; |
case FILESET_TAG: |
- *(familyData->currentFamily->fFileNames.append()) = buff; |
+ if (familyData->currentFontInfo) { |
+ familyData->currentFontInfo->fFileName = buff; |
+ } |
break; |
default: |
// Noop - don't care about any text that's not in the Fonts or Names list |
@@ -70,10 +73,41 @@ 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) { |
+ FontFileInfo* newFileInfo = new FontFileInfo(); |
+ if (attributes) { |
+ int currentAttributeIndex = 0; |
+ while (attributes[currentAttributeIndex]) { |
+ const char* attributeName = attributes[currentAttributeIndex]; |
+ const char* attributeValue = attributes[currentAttributeIndex+1]; |
+ int nameLength = strlen(attributeName); |
+ int valueLength = strlen(attributeValue); |
+ if (strncmp(attributeName, "variant", nameLength) == 0) { |
+ if (strncmp(attributeValue, "elegant", valueLength) == 0) { |
+ newFileInfo->fPaintOptions.setFontVariant(SkPaintOptionsAndroid::kElegant_Variant); |
+ } else if (strncmp(attributeValue, "compact", valueLength) == 0) { |
+ newFileInfo->fPaintOptions.setFontVariant(SkPaintOptionsAndroid::kCompact_Variant); |
+ } |
+ } else if (strncmp(attributeName, "lang", nameLength) == 0) { |
+ newFileInfo->fPaintOptions.setLanguage(attributeValue); |
+ } |
+ //each element is a pair of attributeName/attributeValue string pairs |
+ currentAttributeIndex += 2; |
+ } |
+ } |
+ *(familyData->currentFamily->fFontFiles.append()) = newFileInfo; |
+ familyData->currentFontInfo = newFileInfo; |
+ XML_SetCharacterDataHandler(*familyData->parser, textHandler); |
+} |
+ |
+/** |
* Handler for the start of a tag. The only tags we expect are family, nameset, |
* fileset, name, and file. |
*/ |
-void startElementHandler(void *data, const char *tag, const char **atts) { |
+static void startElementHandler(void *data, const char *tag, const char **atts) { |
FamilyData *familyData = (FamilyData*) data; |
int len = strlen(tag); |
if (strncmp(tag, "family", len)== 0) { |
@@ -89,32 +123,16 @@ void startElementHandler(void *data, const char *tag, const char **atts) { |
familyData->currentFamily->order = value; |
} |
} |
- } else if (len == 7 && strncmp(tag, "nameset", len)== 0) { |
+ } else if (len == 7 && strncmp(tag, "nameset", len) == 0) { |
familyData->currentTag = NAMESET_TAG; |
} else if (len == 7 && strncmp(tag, "fileset", len) == 0) { |
familyData->currentTag = FILESET_TAG; |
} else if (strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) { |
+ // If it's a Name, parse the text inside |
XML_SetCharacterDataHandler(*familyData->parser, textHandler); |
} else if (strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG) { |
- // From JB MR1, the File tag has a "lang" attribute to specify a language specific font file |
- // and the family entry has higher priority than the others without "lang" attribute. |
- bool includeTheEntry = true; |
- for (int i = 0; atts[i] != NULL; i += 2) { |
- const char* attribute = atts[i]; |
- const char* value = atts[i+1]; |
- if (strncmp(attribute, "lang", 4) == 0) { |
- if (strcmp(value, familyData->locale.language) == 0) { |
- // Found matching "lang" attribute. The current Family will have higher priority in the family list. |
- familyData->currentFamilyLangMatch = true; |
- } else { |
- // Don't include the entry if "lang" is specified but not matching. |
- includeTheEntry = false; |
- } |
- } |
- } |
- if (includeTheEntry) { |
- XML_SetCharacterDataHandler(*familyData->parser, textHandler); |
- } |
+ // If it's a file, parse the attributes, then parse the text inside |
+ fontFileElementHandler(familyData, atts); |
} |
} |
@@ -122,21 +140,16 @@ 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. |
*/ |
-void endElementHandler(void *data, const char *tag) { |
+static void endElementHandler(void *data, const char *tag) { |
FamilyData *familyData = (FamilyData*) data; |
int len = strlen(tag); |
if (strncmp(tag, "family", len)== 0) { |
// Done parsing a Family - store the created currentFamily in the families array |
- if (familyData->currentFamilyLangMatch) { |
- *familyData->families.insert(familyData->familyLangMatchCount++) = familyData->currentFamily; |
- familyData->currentFamilyLangMatch = false; |
- } else { |
- *familyData->families.append() = familyData->currentFamily; |
- } |
+ *familyData->families.append() = familyData->currentFamily; |
familyData->currentFamily = NULL; |
- } else if (len == 7 && strncmp(tag, "nameset", len)== 0) { |
+ } else if (len == 7 && strncmp(tag, "nameset", len) == 0) { |
familyData->currentTag = NO_TAG; |
- } else if (len == 7 && strncmp(tag, "fileset", len)== 0) { |
+ } else if (len == 7 && strncmp(tag, "fileset", len) == 0) { |
familyData->currentTag = NO_TAG; |
} else if ((strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) || |
(strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG)) { |
@@ -146,74 +159,15 @@ void endElementHandler(void *data, const char *tag) { |
} |
/** |
- * Read the persistent locale. |
- */ |
-void getLocale(AndroidLocale &locale) |
-{ |
- char propLang[PROP_VALUE_MAX], propRegn[PROP_VALUE_MAX]; |
- __system_property_get("persist.sys.language", propLang); |
- __system_property_get("persist.sys.country", propRegn); |
- |
- if (*propLang == 0 && *propRegn == 0) { |
- /* Set to ro properties, default is en_US */ |
- __system_property_get("ro.product.locale.language", propLang); |
- __system_property_get("ro.product.locale.region", propRegn); |
- if (*propLang == 0 && *propRegn == 0) { |
- strcpy(propLang, "en"); |
- strcpy(propRegn, "US"); |
- } |
- } |
- strncpy(locale.language, propLang, 2); |
- locale.language[2] = '\0'; |
- strncpy(locale.region, propRegn, 2); |
- locale.region[2] = '\0'; |
-} |
- |
-/** |
- * Use the current system locale (language and region) to open the best matching |
- * customization. For example, when the language is Japanese, the sequence might be: |
- * /system/etc/fallback_fonts-ja-JP.xml |
- * /system/etc/fallback_fonts-ja.xml |
- * /system/etc/fallback_fonts.xml |
- */ |
-FILE* openLocalizedFile(const char* origname, const AndroidLocale& locale) { |
- FILE* file = 0; |
- SkString basename; |
- SkString filename; |
- |
- basename.set(origname); |
- // Remove the .xml suffix. We'll add it back in a moment. |
- if (basename.endsWith(".xml")) { |
- basename.resize(basename.size()-4); |
- } |
- // Try first with language and region |
- filename.printf("%s-%s-%s.xml", basename.c_str(), locale.language, locale.region); |
- file = fopen(filename.c_str(), "r"); |
- if (!file) { |
- // If not found, try next with just language |
- filename.printf("%s-%s.xml", basename.c_str(), locale.language); |
- file = fopen(filename.c_str(), "r"); |
- |
- if (!file) { |
- // If still not found, try just the original name |
- file = fopen(origname, "r"); |
- } |
- } |
- return file; |
-} |
- |
-/** |
* This function parses the given filename and stores the results in the given |
* families array. |
*/ |
-void parseConfigFile(const char *filename, SkTDArray<FontFamily*> &families) { |
- AndroidLocale locale; |
- getLocale(locale); |
+static void parseConfigFile(const char *filename, SkTDArray<FontFamily*> &families) { |
XML_Parser parser = XML_ParserCreate(NULL); |
- FamilyData familyData(&parser, families, locale); |
- XML_SetUserData(parser, &familyData); |
+ FamilyData *familyData = new FamilyData(&parser, families); |
+ XML_SetUserData(parser, familyData); |
XML_SetElementHandler(parser, startElementHandler, endElementHandler); |
- FILE *file = openLocalizedFile(filename, locale); |
+ 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 (file == NULL) { |
@@ -230,14 +184,13 @@ void parseConfigFile(const char *filename, SkTDArray<FontFamily*> &families) { |
XML_Parse(parser, buffer, len, done); |
} |
fclose(file); |
- XML_ParserFree(parser); |
} |
-void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { |
+static void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { |
parseConfigFile(SYSTEM_FONTS_FILE, fontFamilies); |
} |
-void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) { |
+static void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) { |
SkTDArray<FontFamily*> vendorFonts; |
parseConfigFile(FALLBACK_FONTS_FILE, fallbackFonts); |
parseConfigFile(VENDOR_FONTS_FILE, vendorFonts); |
@@ -270,21 +223,22 @@ 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 getFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { |
- SkTDArray<FontFamily*> fallbackFonts; |
+void SkFontConfigParser::GetFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { |
getSystemFontFamilies(fontFamilies); |
- getFallbackFontFamilies(fallbackFonts); |
- // Append all fallback fonts to system fonts |
+ // Append all the fallback fonts to system fonts |
+ SkTDArray<FontFamily*> fallbackFonts; |
+ getFallbackFontFamilies(fallbackFonts); |
for (int i = 0; i < fallbackFonts.count(); ++i) { |
+ fallbackFonts[i]->fIsFallbackFont = true; |
*fontFamilies.append() = fallbackFonts[i]; |
} |
} |
-void getTestFontFamilies(SkTDArray<FontFamily*> &fontFamilies, |
- const char* testMainConfigFile, |
- const char* testFallbackConfigFile) { |
+void SkFontConfigParser::GetTestFontFamilies(SkTDArray<FontFamily*> &fontFamilies, |
+ const char* testMainConfigFile, |
+ const char* testFallbackConfigFile) { |
parseConfigFile(testMainConfigFile, fontFamilies); |
SkTDArray<FontFamily*> fallbackFonts; |
@@ -292,6 +246,31 @@ void getTestFontFamilies(SkTDArray<FontFamily*> &fontFamilies, |
// Append all fallback fonts to system fonts |
for (int i = 0; i < fallbackFonts.count(); ++i) { |
+ fallbackFonts[i]->fIsFallbackFont = true; |
*fontFamilies.append() = fallbackFonts[i]; |
} |
} |
+ |
+/** |
+ * Read the persistent locale. |
+ */ |
+void SkFontConfigParser::GetLocale(AndroidLocale &locale) |
+{ |
+ char propLang[PROP_VALUE_MAX], propRegn[PROP_VALUE_MAX]; |
+ __system_property_get("persist.sys.language", propLang); |
+ __system_property_get("persist.sys.country", propRegn); |
+ |
+ if (*propLang == 0 && *propRegn == 0) { |
+ /* Set to ro properties, default is en_US */ |
+ __system_property_get("ro.product.locale.language", propLang); |
+ __system_property_get("ro.product.locale.region", propRegn); |
+ if (*propLang == 0 && *propRegn == 0) { |
+ strcpy(propLang, "en"); |
+ strcpy(propRegn, "US"); |
+ } |
+ } |
+ strncpy(locale.language, propLang, 2); |
+ locale.language[2] = '\0'; |
+ strncpy(locale.region, propRegn, 2); |
+ locale.region[2] = '\0'; |
+} |