Index: src/ports/SkFontConfigParser_android.cpp |
diff --git a/src/ports/SkFontConfigParser_android.cpp b/src/ports/SkFontConfigParser_android.cpp |
index 9bab84556b105f2f3dc06933a620e48aa4d2311e..2535d69e7f5a23cf5ccd07b1a0a17b822b0259a7 100644 |
--- a/src/ports/SkFontConfigParser_android.cpp |
+++ b/src/ports/SkFontConfigParser_android.cpp |
@@ -59,7 +59,7 @@ enum CurrentTag { |
*/ |
struct FamilyData { |
FamilyData(XML_Parser parser, SkTDArray<FontFamily*>& families, |
- const SkString& basePath, bool isFallback) |
+ const SkString& basePath, bool isFallback, const char* filename) |
: fParser(parser) |
, fFamilies(families) |
, fCurrentFamily(NULL) |
@@ -68,6 +68,7 @@ struct FamilyData { |
, fVersion(0) |
, fBasePath(basePath) |
, fIsFallback(isFallback) |
+ , fFilename(filename) |
{ }; |
XML_Parser fParser; // The expat parser doing the work, owned by caller |
@@ -78,6 +79,7 @@ struct FamilyData { |
int fVersion; // The version of the file parsed. |
const SkString& fBasePath; // The current base path. |
const bool fIsFallback; // Indicates the file being parsed is a fallback file |
+ const char* fFilename; // The name of the file currently being parsed. |
}; |
/** Parses a null terminated string into an integer type, checking for overflow. |
@@ -113,12 +115,21 @@ static bool memeq(const char* s1, const char* s2, size_t n1, size_t n2) { |
#define ATTS_NON_NULL(a, i) (a[i] != NULL && a[i+1] != NULL) |
+#define SK_FONTCONFIGPARSER_PREFIX "[SkFontConfigParser] " |
+ |
+#define SK_FONTCONFIGPARSER_WARNING(message, ...) SkDebugf( \ |
+ SK_FONTCONFIGPARSER_PREFIX "%s:%d:%d: warning: " message "\n", \ |
+ self->fFilename, \ |
+ XML_GetCurrentLineNumber(self->fParser), \ |
+ XML_GetCurrentColumnNumber(self->fParser), \ |
+ ##__VA_ARGS__); |
+ |
namespace lmpParser { |
static void family_element_handler(FontFamily* family, const char** attributes) { |
- // A non-fallback <family> tag must have a canonical name attribute. |
- // A fallback <family> tag has no name, and may have lang and variant |
- // attributes. |
+ // A <family> element without a 'name' (string) attribute is a fallback font. |
+ // The element may have 'lang' (string) and 'variant' ("elegant", "compact") attributes. |
+ // The element should contain <font> elements. |
family->fIsFallbackFont = true; |
for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
const char* name = attributes[i]; |
@@ -132,7 +143,6 @@ static void family_element_handler(FontFamily* family, const char** attributes) |
} else if (MEMEQ("lang", name, nameLen)) { |
family->fLanguage = SkLanguage(value, valueLen); |
} else if (MEMEQ("variant", name, nameLen)) { |
- // Value should be either elegant or compact. |
if (MEMEQ("elegant", value, valueLen)) { |
family->fVariant = kElegant_FontVariant; |
} else if (MEMEQ("compact", value, valueLen)) { |
@@ -148,8 +158,9 @@ static void XMLCALL font_file_name_handler(void* data, const char* s, int len) { |
} |
static void font_element_handler(FamilyData* self, FontFileInfo* file, const char** attributes) { |
- // A <font> should have weight (integer) and style (normal, italic) attributes. |
- // NOTE: we ignore the style. |
+ // A <font> element should be contained in a <family> element. |
+ // The element may have 'weight' (non-negative integer), 'style' ("normal", "italic"), |
+ // and 'index' (non-negative integer) attributes. |
// The element should contain a filename. |
for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
const char* name = attributes[i]; |
@@ -157,7 +168,7 @@ static void font_element_handler(FamilyData* self, FontFileInfo* file, const cha |
size_t nameLen = strlen(name); |
if (MEMEQ("weight", name, nameLen)) { |
if (!parse_non_negative_integer(value, &file->fWeight)) { |
- SkDebugf("---- Font weight %s (INVALID)", value); |
+ SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid weight", value); |
} |
} else if (MEMEQ("style", name, nameLen)) { |
size_t valueLen = strlen(value); |
@@ -168,7 +179,7 @@ static void font_element_handler(FamilyData* self, FontFileInfo* file, const cha |
} |
} else if (MEMEQ("index", name, nameLen)) { |
if (!parse_non_negative_integer(value, &file->fIndex)) { |
- SkDebugf("---- Font index %s (INVALID)", value); |
+ SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid index", value); |
} |
} |
} |
@@ -188,11 +199,13 @@ static FontFamily* find_family(FamilyData* self, const SkString& familyName) { |
} |
static void alias_element_handler(FamilyData* self, const char** attributes) { |
- // An <alias> must have name and to attributes. |
- // It may have weight (integer). |
- // If it *does not* have a weight, it is a variant name for a <family>. |
- // If it *does* have a weight, it names the <font>(s) of a specific weight |
- // from a <family>. |
+ // A <alias> element must have 'name' (string) and 'to' (string) attributes. |
+ // The element may also have a 'weight' (non-negative integer) attribute. |
+ // The 'name' introduces a new family name. |
+ // The 'to' specifies which (previous) <family> to alias. |
+ // If it *does not* have a weight, 'name' is an alias for the entire 'to' <family>. |
+ // If it *does* have a weight, 'name' is a new family consisting of the <font>(s) with 'weight' |
+ // from the 'to' <family>. |
SkString aliasName; |
SkString to; |
@@ -208,7 +221,7 @@ static void alias_element_handler(FamilyData* self, const char** attributes) { |
to.set(value); |
} else if (MEMEQ("weight", name, nameLen)) { |
if (!parse_non_negative_integer(value, &weight)) { |
- SkDebugf("---- Font weight %s (INVALID)", value); |
+ SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid weight", value); |
} |
} |
} |
@@ -216,7 +229,7 @@ static void alias_element_handler(FamilyData* self, const char** attributes) { |
// Assumes that the named family is already declared |
FontFamily* targetFamily = find_family(self, to); |
if (!targetFamily) { |
- SkDebugf("---- Font alias target %s (NOT FOUND)", to.c_str()); |
+ SK_FONTCONFIGPARSER_WARNING("'%s' alias target not found", to.c_str()); |
return; |
} |
@@ -299,31 +312,35 @@ static void font_file_element_handler(FamilyData* self, const char** attributes) |
FontFileInfo& newFileInfo = currentFamily.fFonts.push_back(); |
if (attributes) { |
for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
- const char* attributeName = attributes[i]; |
- const char* attributeValue = attributes[i+1]; |
- size_t nameLength = strlen(attributeName); |
- size_t valueLength = strlen(attributeValue); |
- if (MEMEQ("variant", attributeName, nameLength)) { |
+ const char* name = attributes[i]; |
+ const char* value = attributes[i+1]; |
+ size_t nameLen = strlen(name); |
+ size_t valueLen = strlen(value); |
+ if (MEMEQ("variant", name, nameLen)) { |
const FontVariant prevVariant = currentFamily.fVariant; |
- if (MEMEQ("elegant", attributeValue, valueLength)) { |
+ if (MEMEQ("elegant", value, valueLen)) { |
currentFamily.fVariant = kElegant_FontVariant; |
- } else if (MEMEQ("compact", attributeValue, valueLength)) { |
+ } else if (MEMEQ("compact", value, valueLen)) { |
currentFamily.fVariant = kCompact_FontVariant; |
} |
if (currentFamily.fFonts.count() > 1 && currentFamily.fVariant != prevVariant) { |
- SkDebugf("Every font file within a family must have identical variants"); |
+ SK_FONTCONFIGPARSER_WARNING("'%s' unexpected variant found\n" |
+ "Note: Every font file within a family must have identical variants.", |
+ value); |
} |
- } else if (MEMEQ("lang", attributeName, nameLength)) { |
+ } else if (MEMEQ("lang", name, nameLen)) { |
SkLanguage prevLang = currentFamily.fLanguage; |
- currentFamily.fLanguage = SkLanguage(attributeValue, valueLength); |
+ currentFamily.fLanguage = SkLanguage(value, valueLen); |
if (currentFamily.fFonts.count() > 1 && currentFamily.fLanguage != prevLang) { |
- SkDebugf("Every font file within a family must have identical languages"); |
+ SK_FONTCONFIGPARSER_WARNING("'%s' unexpected language found\n" |
+ "Note: Every font file within a family must have identical languages.", |
+ value); |
} |
- } else if (MEMEQ("index", attributeName, nameLength)) { |
- if (!parse_non_negative_integer(attributeValue, &newFileInfo.fIndex)) { |
- SkDebugf("---- SystemFonts index=%s (INVALID)", attributeValue); |
+ } else if (MEMEQ("index", name, nameLen)) { |
+ if (!parse_non_negative_integer(value, &newFileInfo.fIndex)) { |
+ SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid index", value); |
} |
} |
} |
@@ -340,7 +357,7 @@ static void XMLCALL start_element_handler(void* data, const char* tag, const cha |
FamilyData* self = static_cast<FamilyData*>(data); |
size_t len = strlen(tag); |
if (MEMEQ("familyset", tag, len)) { |
- // The familyset tag has an optional "version" attribute with an integer value >= 0 |
+ // The <familyset> element has an optional 'version' (non-negative integer) attribute. |
for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
size_t nameLen = strlen(attributes[i]); |
if (!MEMEQ("version", attributes[i], nameLen)) continue; |
@@ -355,8 +372,8 @@ static void XMLCALL start_element_handler(void* data, const char* tag, const cha |
} |
} else if (MEMEQ("family", tag, len)) { |
self->fCurrentFamily.reset(new FontFamily(self->fBasePath, self->fIsFallback)); |
- // The Family tag has an optional "order" attribute with an integer value >= 0 |
- // If this attribute does not exist, the default value is -1 |
+ // The <family> element has an optional 'order' (non-negative integer) attribute. |
+ // If this attribute does not exist, the default value is -1. |
for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
const char* valueString = attributes[i+1]; |
int value; |
@@ -412,7 +429,7 @@ static void XMLCALL xml_entity_decl_handler(void *data, |
const XML_Char *notationName) |
{ |
FamilyData* self = static_cast<FamilyData*>(data); |
- SkDebugf("Entity declaration %s found, stopping processing.", entityName); |
+ SK_FONTCONFIGPARSER_WARNING("'%s' entity declaration found, stopping processing", entityName); |
XML_StopParser(self->fParser, XML_FALSE); |
} |
@@ -437,18 +454,18 @@ static int parse_config_file(const char* filename, SkTDArray<FontFamily*>& famil |
// 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.isValid()) { |
- SkDebugf("File %s could not be opened.\n", filename); |
+ SkDebugf(SK_FONTCONFIGPARSER_PREFIX "'%s' could not be opened\n", filename); |
return -1; |
} |
SkAutoTCallVProc<remove_ptr<XML_Parser>::type, XML_ParserFree> parser( |
XML_ParserCreate_MM(NULL, &sk_XML_alloc, NULL)); |
if (!parser) { |
- SkDebugf("Could not create XML parser.\n"); |
+ SkDebugf(SK_FONTCONFIGPARSER_PREFIX "could not create XML parser\n"); |
return -1; |
} |
- FamilyData self(parser, families, basePath, isFallback); |
+ FamilyData self(parser, families, basePath, isFallback, filename); |
XML_SetUserData(parser, &self); |
// Disable entity processing, to inhibit internal entity expansion. See expat CVE-2013-0340 |
@@ -466,7 +483,7 @@ static int parse_config_file(const char* filename, SkTDArray<FontFamily*>& famil |
while (!done) { |
void* buffer = XML_GetBuffer(parser, bufferSize); |
if (!buffer) { |
- SkDebugf("Could not buffer enough to continue.\n"); |
+ SkDebugf(SK_FONTCONFIGPARSER_PREFIX "could not buffer enough to continue\n"); |
return -1; |
} |
size_t len = file.read(buffer, bufferSize); |
@@ -476,10 +493,9 @@ static int parse_config_file(const char* filename, SkTDArray<FontFamily*>& famil |
XML_Error error = XML_GetErrorCode(parser); |
int line = XML_GetCurrentLineNumber(parser); |
int column = XML_GetCurrentColumnNumber(parser); |
- int index = XML_GetCurrentByteIndex(parser); |
const XML_LChar* errorString = XML_ErrorString(error); |
- SkDebugf("Line: %d Column: %d (Offset: %d) Error %d: %s.\n", |
- line, column, index, error, errorString); |
+ SkDebugf(SK_FONTCONFIGPARSER_PREFIX "%s:%d:%d error %d: %s.\n", |
+ filename, line, column, error, errorString); |
return -1; |
} |
} |