| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 The Android Open Source Project | 2 * Copyright 2011 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkFontConfigParser_android.h" | 8 #include "SkFontConfigParser_android.h" |
| 9 #include "SkFontMgr_android.h" | 9 #include "SkFontMgr_android.h" |
| 10 #include "SkStream.h" | 10 #include "SkStream.h" |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 | 108 |
| 109 static bool memeq(const char* s1, const char* s2, size_t n1, size_t n2) { | 109 static bool memeq(const char* s1, const char* s2, size_t n1, size_t n2) { |
| 110 return n1 == n2 && 0 == memcmp(s1, s2, n1); | 110 return n1 == n2 && 0 == memcmp(s1, s2, n1); |
| 111 } | 111 } |
| 112 #define MEMEQ(c, s, n) memeq(c, s, sizeof(c) - 1, n) | 112 #define MEMEQ(c, s, n) memeq(c, s, sizeof(c) - 1, n) |
| 113 | 113 |
| 114 #define ATTS_NON_NULL(a, i) (a[i] != NULL && a[i+1] != NULL) | 114 #define ATTS_NON_NULL(a, i) (a[i] != NULL && a[i+1] != NULL) |
| 115 | 115 |
| 116 namespace lmpParser { | 116 namespace lmpParser { |
| 117 | 117 |
| 118 void familyElementHandler(FontFamily* family, const char** attributes) { | 118 static void family_element_handler(FontFamily* family, const char** attributes)
{ |
| 119 // A non-fallback <family> tag must have a canonical name attribute. | 119 // A non-fallback <family> tag must have a canonical name attribute. |
| 120 // A fallback <family> tag has no name, and may have lang and variant | 120 // A fallback <family> tag has no name, and may have lang and variant |
| 121 // attributes. | 121 // attributes. |
| 122 family->fIsFallbackFont = true; | 122 family->fIsFallbackFont = true; |
| 123 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { | 123 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
| 124 const char* name = attributes[i]; | 124 const char* name = attributes[i]; |
| 125 const char* value = attributes[i+1]; | 125 const char* value = attributes[i+1]; |
| 126 size_t nameLen = strlen(name); | 126 size_t nameLen = strlen(name); |
| 127 size_t valueLen = strlen(value); | 127 size_t valueLen = strlen(value); |
| 128 if (MEMEQ("name", name, nameLen)) { | 128 if (MEMEQ("name", name, nameLen)) { |
| 129 SkAutoAsciiToLC tolc(value); | 129 SkAutoAsciiToLC tolc(value); |
| 130 family->fNames.push_back().set(tolc.lc()); | 130 family->fNames.push_back().set(tolc.lc()); |
| 131 family->fIsFallbackFont = false; | 131 family->fIsFallbackFont = false; |
| 132 } else if (MEMEQ("lang", name, nameLen)) { | 132 } else if (MEMEQ("lang", name, nameLen)) { |
| 133 family->fLanguage = SkLanguage(value, valueLen); | 133 family->fLanguage = SkLanguage(value, valueLen); |
| 134 } else if (MEMEQ("variant", name, nameLen)) { | 134 } else if (MEMEQ("variant", name, nameLen)) { |
| 135 // Value should be either elegant or compact. | 135 // Value should be either elegant or compact. |
| 136 if (MEMEQ("elegant", value, valueLen)) { | 136 if (MEMEQ("elegant", value, valueLen)) { |
| 137 family->fVariant = kElegant_FontVariant; | 137 family->fVariant = kElegant_FontVariant; |
| 138 } else if (MEMEQ("compact", value, valueLen)) { | 138 } else if (MEMEQ("compact", value, valueLen)) { |
| 139 family->fVariant = kCompact_FontVariant; | 139 family->fVariant = kCompact_FontVariant; |
| 140 } | 140 } |
| 141 } | 141 } |
| 142 } | 142 } |
| 143 } | 143 } |
| 144 | 144 |
| 145 void XMLCALL fontFileNameHandler(void* data, const char* s, int len) { | 145 static void XMLCALL font_file_name_handler(void* data, const char* s, int len) { |
| 146 FamilyData* self = static_cast<FamilyData*>(data); | 146 FamilyData* self = static_cast<FamilyData*>(data); |
| 147 self->fCurrentFontInfo->fFileName.append(s, len); | 147 self->fCurrentFontInfo->fFileName.append(s, len); |
| 148 } | 148 } |
| 149 | 149 |
| 150 void fontElementHandler(FamilyData* self, FontFileInfo* file, const char** attri
butes) { | 150 static void font_element_handler(FamilyData* self, FontFileInfo* file, const cha
r** attributes) { |
| 151 // A <font> should have weight (integer) and style (normal, italic) attribut
es. | 151 // A <font> should have weight (integer) and style (normal, italic) attribut
es. |
| 152 // NOTE: we ignore the style. | 152 // NOTE: we ignore the style. |
| 153 // The element should contain a filename. | 153 // The element should contain a filename. |
| 154 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { | 154 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
| 155 const char* name = attributes[i]; | 155 const char* name = attributes[i]; |
| 156 const char* value = attributes[i+1]; | 156 const char* value = attributes[i+1]; |
| 157 size_t nameLen = strlen(name); | 157 size_t nameLen = strlen(name); |
| 158 if (MEMEQ("weight", name, nameLen)) { | 158 if (MEMEQ("weight", name, nameLen)) { |
| 159 if (!parse_non_negative_integer(value, &file->fWeight)) { | 159 if (!parse_non_negative_integer(value, &file->fWeight)) { |
| 160 SkDebugf("---- Font weight %s (INVALID)", value); | 160 SkDebugf("---- Font weight %s (INVALID)", value); |
| 161 } | 161 } |
| 162 } | 162 } |
| 163 } | 163 } |
| 164 XML_SetCharacterDataHandler(self->fParser, fontFileNameHandler); | 164 XML_SetCharacterDataHandler(self->fParser, font_file_name_handler); |
| 165 } | 165 } |
| 166 | 166 |
| 167 FontFamily* findFamily(FamilyData* self, const SkString& familyName) { | 167 static FontFamily* find_family(FamilyData* self, const SkString& familyName) { |
| 168 for (int i = 0; i < self->fFamilies.count(); i++) { | 168 for (int i = 0; i < self->fFamilies.count(); i++) { |
| 169 FontFamily* candidate = self->fFamilies[i]; | 169 FontFamily* candidate = self->fFamilies[i]; |
| 170 for (int j = 0; j < candidate->fNames.count(); j++) { | 170 for (int j = 0; j < candidate->fNames.count(); j++) { |
| 171 if (candidate->fNames[j] == familyName) { | 171 if (candidate->fNames[j] == familyName) { |
| 172 return candidate; | 172 return candidate; |
| 173 } | 173 } |
| 174 } | 174 } |
| 175 } | 175 } |
| 176 return NULL; | 176 return NULL; |
| 177 } | 177 } |
| 178 | 178 |
| 179 void aliasElementHandler(FamilyData* self, const char** attributes) { | 179 static void alias_element_handler(FamilyData* self, const char** attributes) { |
| 180 // An <alias> must have name and to attributes. | 180 // An <alias> must have name and to attributes. |
| 181 // It may have weight (integer). | 181 // It may have weight (integer). |
| 182 // If it *does not* have a weight, it is a variant name for a <family>. | 182 // If it *does not* have a weight, it is a variant name for a <family>. |
| 183 // If it *does* have a weight, it names the <font>(s) of a specific weight | 183 // If it *does* have a weight, it names the <font>(s) of a specific weight |
| 184 // from a <family>. | 184 // from a <family>. |
| 185 | 185 |
| 186 SkString aliasName; | 186 SkString aliasName; |
| 187 SkString to; | 187 SkString to; |
| 188 int weight = 0; | 188 int weight = 0; |
| 189 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { | 189 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
| 190 const char* name = attributes[i]; | 190 const char* name = attributes[i]; |
| 191 const char* value = attributes[i+1]; | 191 const char* value = attributes[i+1]; |
| 192 size_t nameLen = strlen(name); | 192 size_t nameLen = strlen(name); |
| 193 if (MEMEQ("name", name, nameLen)) { | 193 if (MEMEQ("name", name, nameLen)) { |
| 194 SkAutoAsciiToLC tolc(value); | 194 SkAutoAsciiToLC tolc(value); |
| 195 aliasName.set(tolc.lc()); | 195 aliasName.set(tolc.lc()); |
| 196 } else if (MEMEQ("to", name, nameLen)) { | 196 } else if (MEMEQ("to", name, nameLen)) { |
| 197 to.set(value); | 197 to.set(value); |
| 198 } else if (MEMEQ("weight", name, nameLen)) { | 198 } else if (MEMEQ("weight", name, nameLen)) { |
| 199 if (!parse_non_negative_integer(value, &weight)) { | 199 if (!parse_non_negative_integer(value, &weight)) { |
| 200 SkDebugf("---- Font weight %s (INVALID)", value); | 200 SkDebugf("---- Font weight %s (INVALID)", value); |
| 201 } | 201 } |
| 202 } | 202 } |
| 203 } | 203 } |
| 204 | 204 |
| 205 // Assumes that the named family is already declared | 205 // Assumes that the named family is already declared |
| 206 FontFamily* targetFamily = findFamily(self, to); | 206 FontFamily* targetFamily = find_family(self, to); |
| 207 if (!targetFamily) { | 207 if (!targetFamily) { |
| 208 SkDebugf("---- Font alias target %s (NOT FOUND)", to.c_str()); | 208 SkDebugf("---- Font alias target %s (NOT FOUND)", to.c_str()); |
| 209 return; | 209 return; |
| 210 } | 210 } |
| 211 | 211 |
| 212 if (weight) { | 212 if (weight) { |
| 213 FontFamily* family = new FontFamily(targetFamily->fBasePath, self->fIsFa
llback); | 213 FontFamily* family = new FontFamily(targetFamily->fBasePath, self->fIsFa
llback); |
| 214 family->fNames.push_back().set(aliasName); | 214 family->fNames.push_back().set(aliasName); |
| 215 | 215 |
| 216 for (int i = 0; i < targetFamily->fFonts.count(); i++) { | 216 for (int i = 0; i < targetFamily->fFonts.count(); i++) { |
| 217 if (targetFamily->fFonts[i].fWeight == weight) { | 217 if (targetFamily->fFonts[i].fWeight == weight) { |
| 218 family->fFonts.push_back(targetFamily->fFonts[i]); | 218 family->fFonts.push_back(targetFamily->fFonts[i]); |
| 219 } | 219 } |
| 220 } | 220 } |
| 221 *self->fFamilies.append() = family; | 221 *self->fFamilies.append() = family; |
| 222 } else { | 222 } else { |
| 223 targetFamily->fNames.push_back().set(aliasName); | 223 targetFamily->fNames.push_back().set(aliasName); |
| 224 } | 224 } |
| 225 } | 225 } |
| 226 | 226 |
| 227 void XMLCALL startElementHandler(void* data, const char* tag, const char** attri
butes) { | 227 static void XMLCALL start_element_handler(void* data, const char* tag, const cha
r** attributes) { |
| 228 FamilyData* self = static_cast<FamilyData*>(data); | 228 FamilyData* self = static_cast<FamilyData*>(data); |
| 229 size_t len = strlen(tag); | 229 size_t len = strlen(tag); |
| 230 if (MEMEQ("family", tag, len)) { | 230 if (MEMEQ("family", tag, len)) { |
| 231 self->fCurrentFamily.reset(new FontFamily(self->fBasePath, self->fIsFall
back)); | 231 self->fCurrentFamily.reset(new FontFamily(self->fBasePath, self->fIsFall
back)); |
| 232 familyElementHandler(self->fCurrentFamily, attributes); | 232 family_element_handler(self->fCurrentFamily, attributes); |
| 233 } else if (MEMEQ("font", tag, len)) { | 233 } else if (MEMEQ("font", tag, len)) { |
| 234 FontFileInfo* file = &self->fCurrentFamily->fFonts.push_back(); | 234 FontFileInfo* file = &self->fCurrentFamily->fFonts.push_back(); |
| 235 self->fCurrentFontInfo = file; | 235 self->fCurrentFontInfo = file; |
| 236 fontElementHandler(self, file, attributes); | 236 font_element_handler(self, file, attributes); |
| 237 } else if (MEMEQ("alias", tag, len)) { | 237 } else if (MEMEQ("alias", tag, len)) { |
| 238 aliasElementHandler(self, attributes); | 238 alias_element_handler(self, attributes); |
| 239 } | 239 } |
| 240 } | 240 } |
| 241 | 241 |
| 242 void XMLCALL endElementHandler(void* data, const char* tag) { | 242 static void XMLCALL end_element_handler(void* data, const char* tag) { |
| 243 FamilyData* self = static_cast<FamilyData*>(data); | 243 FamilyData* self = static_cast<FamilyData*>(data); |
| 244 size_t len = strlen(tag); | 244 size_t len = strlen(tag); |
| 245 if (MEMEQ("family", tag, len)) { | 245 if (MEMEQ("family", tag, len)) { |
| 246 *self->fFamilies.append() = self->fCurrentFamily.detach(); | 246 *self->fFamilies.append() = self->fCurrentFamily.detach(); |
| 247 } else if (MEMEQ("font", tag, len)) { | 247 } else if (MEMEQ("font", tag, len)) { |
| 248 XML_SetCharacterDataHandler(self->fParser, NULL); | 248 XML_SetCharacterDataHandler(self->fParser, NULL); |
| 249 } | 249 } |
| 250 } | 250 } |
| 251 | 251 |
| 252 } // lmpParser | 252 } // lmpParser |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 size_t len = strlen(tag); | 330 size_t len = strlen(tag); |
| 331 if (MEMEQ("familyset", tag, len)) { | 331 if (MEMEQ("familyset", tag, len)) { |
| 332 // The familyset tag has an optional "version" attribute with an integer
value >= 0 | 332 // The familyset tag has an optional "version" attribute with an integer
value >= 0 |
| 333 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { | 333 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
| 334 size_t nameLen = strlen(attributes[i]); | 334 size_t nameLen = strlen(attributes[i]); |
| 335 if (!MEMEQ("version", attributes[i], nameLen)) continue; | 335 if (!MEMEQ("version", attributes[i], nameLen)) continue; |
| 336 const char* valueString = attributes[i+1]; | 336 const char* valueString = attributes[i+1]; |
| 337 int version; | 337 int version; |
| 338 if (parse_non_negative_integer(valueString, &version) && (version >=
21)) { | 338 if (parse_non_negative_integer(valueString, &version) && (version >=
21)) { |
| 339 XML_SetElementHandler(self->fParser, | 339 XML_SetElementHandler(self->fParser, |
| 340 lmpParser::startElementHandler, | 340 lmpParser::start_element_handler, |
| 341 lmpParser::endElementHandler); | 341 lmpParser::end_element_handler); |
| 342 self->fVersion = version; | 342 self->fVersion = version; |
| 343 } | 343 } |
| 344 } | 344 } |
| 345 } else if (MEMEQ("family", tag, len)) { | 345 } else if (MEMEQ("family", tag, len)) { |
| 346 self->fCurrentFamily.reset(new FontFamily(self->fBasePath, self->fIsFall
back)); | 346 self->fCurrentFamily.reset(new FontFamily(self->fBasePath, self->fIsFall
back)); |
| 347 // The Family tag has an optional "order" attribute with an integer valu
e >= 0 | 347 // The Family tag has an optional "order" attribute with an integer valu
e >= 0 |
| 348 // If this attribute does not exist, the default value is -1 | 348 // If this attribute does not exist, the default value is -1 |
| 349 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { | 349 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
| 350 const char* valueString = attributes[i+1]; | 350 const char* valueString = attributes[i+1]; |
| 351 int value; | 351 int value; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 const XML_Char *base, | 398 const XML_Char *base, |
| 399 const XML_Char *systemId, | 399 const XML_Char *systemId, |
| 400 const XML_Char *publicId, | 400 const XML_Char *publicId, |
| 401 const XML_Char *notationName) | 401 const XML_Char *notationName) |
| 402 { | 402 { |
| 403 FamilyData* self = static_cast<FamilyData*>(data); | 403 FamilyData* self = static_cast<FamilyData*>(data); |
| 404 SkDebugf("Entity declaration %s found, stopping processing.", entityName); | 404 SkDebugf("Entity declaration %s found, stopping processing.", entityName); |
| 405 XML_StopParser(self->fParser, XML_FALSE); | 405 XML_StopParser(self->fParser, XML_FALSE); |
| 406 } | 406 } |
| 407 | 407 |
| 408 static const XML_Memory_Handling_Suite sk_XML_alloc = { |
| 409 sk_malloc_throw, |
| 410 sk_realloc_throw, |
| 411 sk_free |
| 412 }; |
| 413 |
| 408 template<typename T> struct remove_ptr {typedef T type;}; | 414 template<typename T> struct remove_ptr {typedef T type;}; |
| 409 template<typename T> struct remove_ptr<T*> {typedef T type;}; | 415 template<typename T> struct remove_ptr<T*> {typedef T type;}; |
| 410 | 416 |
| 411 /** | 417 /** |
| 412 * This function parses the given filename and stores the results in the given | 418 * This function parses the given filename and stores the results in the given |
| 413 * families array. Returns the version of the file, negative if the file does no
t exist. | 419 * families array. Returns the version of the file, negative if the file does no
t exist. |
| 414 */ | 420 */ |
| 415 static int parse_config_file(const char* filename, SkTDArray<FontFamily*>& famil
ies, | 421 static int parse_config_file(const char* filename, SkTDArray<FontFamily*>& famil
ies, |
| 416 const SkString& basePath, bool isFallback) | 422 const SkString& basePath, bool isFallback) |
| 417 { | 423 { |
| 418 SkFILEStream file(filename); | 424 SkFILEStream file(filename); |
| 419 | 425 |
| 420 // Some of the files we attempt to parse (in particular, /vendor/etc/fallbac
k_fonts.xml) | 426 // Some of the files we attempt to parse (in particular, /vendor/etc/fallbac
k_fonts.xml) |
| 421 // are optional - failure here is okay because one of these optional files m
ay not exist. | 427 // are optional - failure here is okay because one of these optional files m
ay not exist. |
| 422 if (!file.isValid()) { | 428 if (!file.isValid()) { |
| 423 SkDebugf("File %s could not be opened.\n", filename); | 429 SkDebugf("File %s could not be opened.\n", filename); |
| 424 return -1; | 430 return -1; |
| 425 } | 431 } |
| 426 | 432 |
| 427 SkAutoTCallVProc<remove_ptr<XML_Parser>::type, XML_ParserFree> parser(XML_Pa
rserCreate(NULL)); | 433 SkAutoTCallVProc<remove_ptr<XML_Parser>::type, XML_ParserFree> parser( |
| 434 XML_ParserCreate_MM(NULL, &sk_XML_alloc, NULL)); |
| 428 if (!parser) { | 435 if (!parser) { |
| 429 SkDebugf("Could not create XML parser.\n"); | 436 SkDebugf("Could not create XML parser.\n"); |
| 430 return -1; | 437 return -1; |
| 431 } | 438 } |
| 432 | 439 |
| 433 FamilyData self(parser, families, basePath, isFallback); | 440 FamilyData self(parser, families, basePath, isFallback); |
| 434 XML_SetUserData(parser, &self); | 441 XML_SetUserData(parser, &self); |
| 435 | 442 |
| 436 // Disable entity processing, to inhibit internal entity expansion. See expa
t CVE-2013-0340 | 443 // Disable entity processing, to inhibit internal entity expansion. See expa
t CVE-2013-0340 |
| 437 XML_SetEntityDeclHandler(parser, xml_entity_decl_handler); | 444 XML_SetEntityDeclHandler(parser, xml_entity_decl_handler); |
| 438 | 445 |
| 439 // Start parsing oldschool; switch these in flight if we detect a newer vers
ion of the file. | 446 // Start parsing oldschool; switch these in flight if we detect a newer vers
ion of the file. |
| 440 XML_SetElementHandler(parser, jbParser::start_element_handler, jbParser::end
_element_handler); | 447 XML_SetElementHandler(parser, jbParser::start_element_handler, jbParser::end
_element_handler); |
| 441 | 448 |
| 442 char buffer[512]; | 449 // One would assume it would be faster to have a buffer on the stack and cal
l XML_Parse. |
| 450 // But XML_Parse will call XML_GetBuffer anyway and memmove the passed buffe
r into it. |
| 451 // (Unless XML_CONTEXT_BYTES is undefined, but all users define it.) |
| 452 static const int bufferSize = 512; |
| 443 bool done = false; | 453 bool done = false; |
| 444 while (!done) { | 454 while (!done) { |
| 445 size_t len = file.read(buffer, SK_ARRAY_COUNT(buffer)); | 455 void* buffer = XML_GetBuffer(parser, bufferSize); |
| 456 if (!buffer) { |
| 457 SkDebugf("Could not buffer enough to continue.\n"); |
| 458 return -1; |
| 459 } |
| 460 size_t len = file.read(buffer, bufferSize); |
| 446 done = file.isAtEnd(); | 461 done = file.isAtEnd(); |
| 447 XML_Status status = XML_Parse(parser, buffer, len, done); | 462 XML_Status status = XML_ParseBuffer(parser, len, done); |
| 448 if (XML_STATUS_ERROR == status) { | 463 if (XML_STATUS_ERROR == status) { |
| 449 XML_Error error = XML_GetErrorCode(parser); | 464 XML_Error error = XML_GetErrorCode(parser); |
| 450 int line = XML_GetCurrentLineNumber(parser); | 465 int line = XML_GetCurrentLineNumber(parser); |
| 451 int column = XML_GetCurrentColumnNumber(parser); | 466 int column = XML_GetCurrentColumnNumber(parser); |
| 452 int index = XML_GetCurrentByteIndex(parser); | 467 int index = XML_GetCurrentByteIndex(parser); |
| 453 const XML_LChar* errorString = XML_ErrorString(error); | 468 const XML_LChar* errorString = XML_ErrorString(error); |
| 454 SkDebugf("Line: %d Column: %d (Offset: %d) Error %d: %s.\n", | 469 SkDebugf("Line: %d Column: %d (Offset: %d) Error %d: %s.\n", |
| 455 line, column, index, error, errorString); | 470 line, column, index, error, errorString); |
| 456 return -1; | 471 return -1; |
| 457 } | 472 } |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 const char* tag = fTag.c_str(); | 619 const char* tag = fTag.c_str(); |
| 605 | 620 |
| 606 // strip off the rightmost "-.*" | 621 // strip off the rightmost "-.*" |
| 607 const char* parentTagEnd = strrchr(tag, '-'); | 622 const char* parentTagEnd = strrchr(tag, '-'); |
| 608 if (parentTagEnd == NULL) { | 623 if (parentTagEnd == NULL) { |
| 609 return SkLanguage(); | 624 return SkLanguage(); |
| 610 } | 625 } |
| 611 size_t parentTagLen = parentTagEnd - tag; | 626 size_t parentTagLen = parentTagEnd - tag; |
| 612 return SkLanguage(tag, parentTagLen); | 627 return SkLanguage(tag, parentTagLen); |
| 613 } | 628 } |
| OLD | NEW |