Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: src/ports/SkFontConfigParser_android.cpp

Issue 915443002: Additional cleanups to Android config parsing. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Prevent future bit rot in test debug dump. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « platform_tools/android/gyp/dependencies.gypi ('k') | tests/FontConfigParser.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « platform_tools/android/gyp/dependencies.gypi ('k') | tests/FontConfigParser.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698