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 |