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

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

Issue 888923003: Don't read unecessary font files on Android. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Move reference & to type. 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 | « src/ports/SkFontConfigParser_android.h ('k') | no next file » | 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 "SkTDArray.h" 9 #include "SkTDArray.h"
10 #include "SkTSearch.h" 10 #include "SkTSearch.h"
11 #include "SkTypeface.h" 11 #include "SkTypeface.h"
12 12
13 #include <expat.h> 13 #include <expat.h>
14 #include <dirent.h> 14 #include <dirent.h>
15 #include <stdio.h> 15 #include <stdio.h>
16 16
17 #include <limits> 17 #include <limits>
18 18
19
20
21 // From Android version LMP onwards, all font files collapse into 19 // From Android version LMP onwards, all font files collapse into
22 // /system/etc/fonts.xml. Instead of trying to detect which version 20 // /system/etc/fonts.xml. Instead of trying to detect which version
23 // we're on, try to open fonts.xml; if that fails, fall back to the 21 // we're on, try to open fonts.xml; if that fails, fall back to the
24 // older filename. 22 // older filename.
25 #define LMP_SYSTEM_FONTS_FILE "/system/etc/fonts.xml" 23 #define LMP_SYSTEM_FONTS_FILE "/system/etc/fonts.xml"
26 #define OLD_SYSTEM_FONTS_FILE "/system/etc/system_fonts.xml" 24 #define OLD_SYSTEM_FONTS_FILE "/system/etc/system_fonts.xml"
27 #define FALLBACK_FONTS_FILE "/system/etc/fallback_fonts.xml" 25 #define FALLBACK_FONTS_FILE "/system/etc/fallback_fonts.xml"
28 #define VENDOR_FONTS_FILE "/vendor/etc/fallback_fonts.xml" 26 #define VENDOR_FONTS_FILE "/vendor/etc/fallback_fonts.xml"
29 27
30 #define LOCALE_FALLBACK_FONTS_SYSTEM_DIR "/system/etc" 28 #define LOCALE_FALLBACK_FONTS_SYSTEM_DIR "/system/etc"
(...skipping 13 matching lines...) Expand all
44 // for now. 42 // for now.
45 #define NO_TAG 0 43 #define NO_TAG 0
46 #define NAMESET_TAG 1 44 #define NAMESET_TAG 1
47 #define FILESET_TAG 2 45 #define FILESET_TAG 2
48 46
49 /** 47 /**
50 * The FamilyData structure is passed around by the parser so that each handler 48 * The FamilyData structure is passed around by the parser so that each handler
51 * can read these variables that are relevant to the current parsing. 49 * can read these variables that are relevant to the current parsing.
52 */ 50 */
53 struct FamilyData { 51 struct FamilyData {
54 FamilyData(XML_Parser parser, SkTDArray<FontFamily*> &families) 52 FamilyData(XML_Parser parser, SkTDArray<FontFamily*>& families)
55 : fParser(parser) 53 : fParser(parser)
56 , fFamilies(families) 54 , fFamilies(families)
57 , fCurrentFamily(NULL) 55 , fCurrentFamily(NULL)
58 , fCurrentFontInfo(NULL) 56 , fCurrentFontInfo(NULL)
59 , fCurrentTag(NO_TAG) 57 , fCurrentTag(NO_TAG)
60 { }; 58 , fVersion(0)
59 { }
61 60
62 XML_Parser fParser; // The expat parser doing the work , owned by caller 61 XML_Parser fParser; // The expat parser doing the work , owned by caller
63 SkTDArray<FontFamily*>& fFamilies; // The array to append families, o wned by caller 62 SkTDArray<FontFamily*>& fFamilies; // The array to append families, o wned by caller
64 SkAutoTDelete<FontFamily> fCurrentFamily; // The family being created, owned by this 63 SkAutoTDelete<FontFamily> fCurrentFamily; // The family being created, owned by this
65 FontFileInfo* fCurrentFontInfo; // The fontInfo being created, own ed by currentFamily 64 FontFileInfo* fCurrentFontInfo; // The fontInfo being created, own ed by currentFamily
66 int fCurrentTag; // Flag to indicate when we're in nameset/fileset tags 65 int fCurrentTag; // Flag to indicate when we're in nameset/fileset tags
66 int fVersion; // The version of the file parsed.
67 }; 67 };
68 68
69 /** http://www.w3.org/TR/html-markup/datatypes.html#common.data.integer.non-nega tive-def */ 69 /** http://www.w3.org/TR/html-markup/datatypes.html#common.data.integer.non-nega tive-def */
70 template <typename T> static bool parseNonNegativeInteger(const char* s, T* valu e) { 70 template <typename T> static bool parse_non_negative_integer(const char* s, T* v alue) {
71 SK_COMPILE_ASSERT(std::numeric_limits<T>::is_integer, T_must_be_integer); 71 SK_COMPILE_ASSERT(std::numeric_limits<T>::is_integer, T_must_be_integer);
72 const T nMax = std::numeric_limits<T>::max() / 10; 72 const T nMax = std::numeric_limits<T>::max() / 10;
73 const T dMax = std::numeric_limits<T>::max() - (nMax * 10); 73 const T dMax = std::numeric_limits<T>::max() - (nMax * 10);
74 T n = 0; 74 T n = 0;
75 for (; *s; ++s) { 75 for (; *s; ++s) {
76 // Check if digit 76 // Check if digit
77 if (*s < '0' || '9' < *s) { 77 if (*s < '0' || '9' < *s) {
78 return false; 78 return false;
79 } 79 }
80 int d = *s - '0'; 80 int d = *s - '0';
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 void fontElementHandler(XML_Parser parser, FontFileInfo* file, const char** attr ibutes) { 126 void fontElementHandler(XML_Parser parser, FontFileInfo* file, const char** attr ibutes) {
127 // A <font> should have weight (integer) and style (normal, italic) attribut es. 127 // A <font> should have weight (integer) and style (normal, italic) attribut es.
128 // NOTE: we ignore the style. 128 // NOTE: we ignore the style.
129 // The element should contain a filename. 129 // The element should contain a filename.
130 for (size_t i = 0; attributes[i] != NULL && 130 for (size_t i = 0; attributes[i] != NULL &&
131 attributes[i+1] != NULL; i += 2) { 131 attributes[i+1] != NULL; i += 2) {
132 const char* name = attributes[i]; 132 const char* name = attributes[i];
133 const char* value = attributes[i+1]; 133 const char* value = attributes[i+1];
134 size_t nameLen = strlen(name); 134 size_t nameLen = strlen(name);
135 if (nameLen == 6 && !strncmp("weight", name, nameLen)) { 135 if (nameLen == 6 && !strncmp("weight", name, nameLen)) {
136 if (!parseNonNegativeInteger(value, &file->fWeight)) { 136 if (!parse_non_negative_integer(value, &file->fWeight)) {
137 SkDebugf("---- Font weight %s (INVALID)", value); 137 SkDebugf("---- Font weight %s (INVALID)", value);
138 file->fWeight = 0; 138 file->fWeight = 0;
139 } 139 }
140 } 140 }
141 } 141 }
142 XML_SetCharacterDataHandler(parser, fontFileNameHandler); 142 XML_SetCharacterDataHandler(parser, fontFileNameHandler);
143 } 143 }
144 144
145 FontFamily* findFamily(FamilyData* familyData, const char* familyName) { 145 FontFamily* findFamily(FamilyData* familyData, const char* familyName) {
146 size_t nameLen = strlen(familyName); 146 size_t nameLen = strlen(familyName);
(...skipping 24 matching lines...) Expand all
171 attributes[i+1] != NULL; i += 2) { 171 attributes[i+1] != NULL; i += 2) {
172 const char* name = attributes[i]; 172 const char* name = attributes[i];
173 const char* value = attributes[i+1]; 173 const char* value = attributes[i+1];
174 size_t nameLen = strlen(name); 174 size_t nameLen = strlen(name);
175 if (nameLen == 4 && !strncmp("name", name, nameLen)) { 175 if (nameLen == 4 && !strncmp("name", name, nameLen)) {
176 SkAutoAsciiToLC tolc(value); 176 SkAutoAsciiToLC tolc(value);
177 aliasName.set(tolc.lc()); 177 aliasName.set(tolc.lc());
178 } else if (nameLen == 2 && !strncmp("to", name, nameLen)) { 178 } else if (nameLen == 2 && !strncmp("to", name, nameLen)) {
179 to.set(value); 179 to.set(value);
180 } else if (nameLen == 6 && !strncmp("weight", name, nameLen)) { 180 } else if (nameLen == 6 && !strncmp("weight", name, nameLen)) {
181 parseNonNegativeInteger(value, &weight); 181 parse_non_negative_integer(value, &weight);
182 } 182 }
183 } 183 }
184 184
185 // Assumes that the named family is already declared 185 // Assumes that the named family is already declared
186 FontFamily* targetFamily = findFamily(familyData, to.c_str()); 186 FontFamily* targetFamily = findFamily(familyData, to.c_str());
187 if (!targetFamily) { 187 if (!targetFamily) {
188 SkDebugf("---- Font alias target %s (NOT FOUND)", to.c_str()); 188 SkDebugf("---- Font alias target %s (NOT FOUND)", to.c_str());
189 return; 189 return;
190 } 190 }
191 191
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 } 230 }
231 231
232 } // lmpParser 232 } // lmpParser
233 233
234 namespace jbParser { 234 namespace jbParser {
235 235
236 /** 236 /**
237 * Handler for arbitrary text. This is used to parse the text inside each name 237 * Handler for arbitrary text. This is used to parse the text inside each name
238 * or file tag. The resulting strings are put into the fNames or FontFileInfo ar rays. 238 * or file tag. The resulting strings are put into the fNames or FontFileInfo ar rays.
239 */ 239 */
240 static void textHandler(void* data, const char* s, int len) { 240 static void text_handler(void* data, const char* s, int len) {
241 FamilyData* familyData = (FamilyData*) data; 241 FamilyData* familyData = (FamilyData*) data;
242 // Make sure we're in the right state to store this name information 242 // Make sure we're in the right state to store this name information
243 if (familyData->fCurrentFamily.get() && 243 if (familyData->fCurrentFamily.get() &&
244 (familyData->fCurrentTag == NAMESET_TAG || familyData->fCurrentTag = = FILESET_TAG)) { 244 (familyData->fCurrentTag == NAMESET_TAG || familyData->fCurrentTag = = FILESET_TAG)) {
245 switch (familyData->fCurrentTag) { 245 switch (familyData->fCurrentTag) {
246 case NAMESET_TAG: { 246 case NAMESET_TAG: {
247 SkAutoAsciiToLC tolc(s, len); 247 SkAutoAsciiToLC tolc(s, len);
248 familyData->fCurrentFamily->fNames.push_back().set(tolc.lc(), len); 248 familyData->fCurrentFamily->fNames.push_back().set(tolc.lc(), len);
249 break; 249 break;
250 } 250 }
251 case FILESET_TAG: 251 case FILESET_TAG:
252 if (familyData->fCurrentFontInfo) { 252 if (familyData->fCurrentFontInfo) {
253 familyData->fCurrentFontInfo->fFileName.set(s, len); 253 familyData->fCurrentFontInfo->fFileName.set(s, len);
254 } 254 }
255 break; 255 break;
256 default: 256 default:
257 // Noop - don't care about any text that's not in the Fonts or Names list 257 // Noop - don't care about any text that's not in the Fonts or Names list
258 break; 258 break;
259 } 259 }
260 } 260 }
261 } 261 }
262 262
263 /** 263 /**
264 * Handler for font files. This processes the attributes for language and 264 * Handler for font files. This processes the attributes for language and
265 * variants then lets textHandler handle the actual file name 265 * variants then lets textHandler handle the actual file name
266 */ 266 */
267 static void fontFileElementHandler(FamilyData* familyData, const char** attribut es) { 267 static void font_file_element_handler(FamilyData* familyData, const char** attri butes) {
268 FontFileInfo& newFileInfo = familyData->fCurrentFamily->fFonts.push_back(); 268 FontFileInfo& newFileInfo = familyData->fCurrentFamily->fFonts.push_back();
269 if (attributes) { 269 if (attributes) {
270 size_t currentAttributeIndex = 0; 270 size_t currentAttributeIndex = 0;
271 while (attributes[currentAttributeIndex] && 271 while (attributes[currentAttributeIndex] &&
272 attributes[currentAttributeIndex + 1]) { 272 attributes[currentAttributeIndex + 1]) {
273 const char* attributeName = attributes[currentAttributeIndex]; 273 const char* attributeName = attributes[currentAttributeIndex];
274 const char* attributeValue = attributes[currentAttributeIndex+1]; 274 const char* attributeValue = attributes[currentAttributeIndex+1];
275 size_t nameLength = strlen(attributeName); 275 size_t nameLength = strlen(attributeName);
276 size_t valueLength = strlen(attributeValue); 276 size_t valueLength = strlen(attributeValue);
277 if (nameLength == 7 && strncmp(attributeName, "variant", nameLength) == 0) { 277 if (nameLength == 7 && strncmp(attributeName, "variant", nameLength) == 0) {
(...skipping 13 matching lines...) Expand all
291 } else if (nameLength == 4 && strncmp(attributeName, "lang", nameLen gth) == 0) { 291 } else if (nameLength == 4 && strncmp(attributeName, "lang", nameLen gth) == 0) {
292 SkLanguage prevLang = familyData->fCurrentFamily->fLanguage; 292 SkLanguage prevLang = familyData->fCurrentFamily->fLanguage;
293 familyData->fCurrentFamily->fLanguage = SkLanguage(attributeValu e); 293 familyData->fCurrentFamily->fLanguage = SkLanguage(attributeValu e);
294 if (familyData->fCurrentFamily->fFonts.count() > 1 && 294 if (familyData->fCurrentFamily->fFonts.count() > 1 &&
295 familyData->fCurrentFamily->fLanguage != prevLang) { 295 familyData->fCurrentFamily->fLanguage != prevLang) {
296 SkDebugf("Every font file within a family must have identica l languages"); 296 SkDebugf("Every font file within a family must have identica l languages");
297 sk_throw(); 297 sk_throw();
298 } 298 }
299 } else if (nameLength == 5 && strncmp(attributeName, "index", nameLe ngth) == 0) { 299 } else if (nameLength == 5 && strncmp(attributeName, "index", nameLe ngth) == 0) {
300 int value; 300 int value;
301 if (parseNonNegativeInteger(attributeValue, &value)) { 301 if (parse_non_negative_integer(attributeValue, &value)) {
302 newFileInfo.fIndex = value; 302 newFileInfo.fIndex = value;
303 } else { 303 } else {
304 SkDebugf("---- SystemFonts index=%s (INVALID)", attributeVal ue); 304 SkDebugf("---- SystemFonts index=%s (INVALID)", attributeVal ue);
305 } 305 }
306 } 306 }
307 //each element is a pair of attributeName/attributeValue string pair s 307 //each element is a pair of attributeName/attributeValue string pair s
308 currentAttributeIndex += 2; 308 currentAttributeIndex += 2;
309 } 309 }
310 } 310 }
311 familyData->fCurrentFontInfo = &newFileInfo; 311 familyData->fCurrentFontInfo = &newFileInfo;
312 XML_SetCharacterDataHandler(familyData->fParser, textHandler); 312 XML_SetCharacterDataHandler(familyData->fParser, text_handler);
313 } 313 }
314 314
315 /** 315 /**
316 * Handler for the start of a tag. The only tags we expect are familyset, family , 316 * Handler for the start of a tag. The only tags we expect are familyset, family ,
317 * nameset, fileset, name, and file. 317 * nameset, fileset, name, and file.
318 */ 318 */
319 static void startElementHandler(void* data, const char* tag, const char** atts) { 319 static void start_element_handler(void* data, const char* tag, const char** atts ) {
320 FamilyData* familyData = (FamilyData*) data; 320 FamilyData* familyData = (FamilyData*) data;
321 size_t len = strlen(tag); 321 size_t len = strlen(tag);
322 if (len == 9 && strncmp(tag, "familyset", len) == 0) { 322 if (len == 9 && strncmp(tag, "familyset", len) == 0) {
323 // The familyset tag has an optional "version" attribute with an integer value >= 0 323 // The familyset tag has an optional "version" attribute with an integer value >= 0
324 for (size_t i = 0; atts[i] != NULL && 324 for (size_t i = 0; atts[i] != NULL &&
325 atts[i+1] != NULL; i += 2) { 325 atts[i+1] != NULL; i += 2) {
326 size_t nameLen = strlen(atts[i]); 326 size_t nameLen = strlen(atts[i]);
327 if (nameLen == 7 && strncmp(atts[i], "version", nameLen)) continue; 327 if (nameLen == 7 && strncmp(atts[i], "version", nameLen)) continue;
328 const char* valueString = atts[i+1]; 328 const char* valueString = atts[i+1];
329 int version; 329 int version;
330 if (parseNonNegativeInteger(valueString, &version) && (version >= 21 )) { 330 if (parse_non_negative_integer(valueString, &version) && (version >= 21)) {
331 XML_SetElementHandler(familyData->fParser, 331 XML_SetElementHandler(familyData->fParser,
332 lmpParser::startElementHandler, 332 lmpParser::startElementHandler,
333 lmpParser::endElementHandler); 333 lmpParser::endElementHandler);
334 familyData->fVersion = version;
334 } 335 }
335 } 336 }
336 } else if (len == 6 && strncmp(tag, "family", len) == 0) { 337 } else if (len == 6 && strncmp(tag, "family", len) == 0) {
337 familyData->fCurrentFamily.reset(new FontFamily()); 338 familyData->fCurrentFamily.reset(new FontFamily());
338 // The Family tag has an optional "order" attribute with an integer valu e >= 0 339 // The Family tag has an optional "order" attribute with an integer valu e >= 0
339 // If this attribute does not exist, the default value is -1 340 // If this attribute does not exist, the default value is -1
340 for (size_t i = 0; atts[i] != NULL && 341 for (size_t i = 0; atts[i] != NULL &&
341 atts[i+1] != NULL; i += 2) { 342 atts[i+1] != NULL; i += 2) {
342 const char* valueString = atts[i+1]; 343 const char* valueString = atts[i+1];
343 int value; 344 int value;
344 if (parseNonNegativeInteger(valueString, &value)) { 345 if (parse_non_negative_integer(valueString, &value)) {
345 familyData->fCurrentFamily->fOrder = value; 346 familyData->fCurrentFamily->fOrder = value;
346 } 347 }
347 } 348 }
348 } else if (len == 7 && strncmp(tag, "nameset", len) == 0) { 349 } else if (len == 7 && strncmp(tag, "nameset", len) == 0) {
349 familyData->fCurrentTag = NAMESET_TAG; 350 familyData->fCurrentTag = NAMESET_TAG;
350 } else if (len == 7 && strncmp(tag, "fileset", len) == 0) { 351 } else if (len == 7 && strncmp(tag, "fileset", len) == 0) {
351 familyData->fCurrentTag = FILESET_TAG; 352 familyData->fCurrentTag = FILESET_TAG;
352 } else if (len == 4 && strncmp(tag, "name", len) == 0 && familyData->fCurren tTag == NAMESET_TAG) { 353 } else if (len == 4 && strncmp(tag, "name", len) == 0 && familyData->fCurren tTag == NAMESET_TAG) {
353 // If it's a Name, parse the text inside 354 // If it's a Name, parse the text inside
354 XML_SetCharacterDataHandler(familyData->fParser, textHandler); 355 XML_SetCharacterDataHandler(familyData->fParser, text_handler);
355 } else if (len == 4 && strncmp(tag, "file", len) == 0 && familyData->fCurren tTag == FILESET_TAG) { 356 } else if (len == 4 && strncmp(tag, "file", len) == 0 && familyData->fCurren tTag == FILESET_TAG) {
356 // If it's a file, parse the attributes, then parse the text inside 357 // If it's a file, parse the attributes, then parse the text inside
357 fontFileElementHandler(familyData, atts); 358 font_file_element_handler(familyData, atts);
358 } 359 }
359 } 360 }
360 361
361 /** 362 /**
362 * Handler for the end of tags. We only care about family, nameset, fileset, 363 * Handler for the end of tags. We only care about family, nameset, fileset,
363 * name, and file. 364 * name, and file.
364 */ 365 */
365 static void endElementHandler(void* data, const char* tag) { 366 static void end_element_handler(void* data, const char* tag) {
366 FamilyData* familyData = (FamilyData*) data; 367 FamilyData* familyData = (FamilyData*) data;
367 size_t len = strlen(tag); 368 size_t len = strlen(tag);
368 if (len == 6 && strncmp(tag, "family", len)== 0) { 369 if (len == 6 && strncmp(tag, "family", len)== 0) {
369 // Done parsing a Family - store the created currentFamily in the famili es array 370 // Done parsing a Family - store the created currentFamily in the famili es array
370 *familyData->fFamilies.append() = familyData->fCurrentFamily.detach(); 371 *familyData->fFamilies.append() = familyData->fCurrentFamily.detach();
371 } else if (len == 7 && strncmp(tag, "nameset", len) == 0) { 372 } else if (len == 7 && strncmp(tag, "nameset", len) == 0) {
372 familyData->fCurrentTag = NO_TAG; 373 familyData->fCurrentTag = NO_TAG;
373 } else if (len == 7 && strncmp(tag, "fileset", len) == 0) { 374 } else if (len == 7 && strncmp(tag, "fileset", len) == 0) {
374 familyData->fCurrentTag = NO_TAG; 375 familyData->fCurrentTag = NO_TAG;
375 } else if ((len == 4 && 376 } else if ((len == 4 &&
376 strncmp(tag, "name", len) == 0 && 377 strncmp(tag, "name", len) == 0 &&
377 familyData->fCurrentTag == NAMESET_TAG) || 378 familyData->fCurrentTag == NAMESET_TAG) ||
378 (len == 4 && 379 (len == 4 &&
379 strncmp(tag, "file", len) == 0 && 380 strncmp(tag, "file", len) == 0 &&
380 familyData->fCurrentTag == FILESET_TAG)) { 381 familyData->fCurrentTag == FILESET_TAG)) {
381 // Disable the arbitrary text handler installed to load Name data 382 // Disable the arbitrary text handler installed to load Name data
382 XML_SetCharacterDataHandler(familyData->fParser, NULL); 383 XML_SetCharacterDataHandler(familyData->fParser, NULL);
383 } 384 }
384 } 385 }
385 386
386 } // namespace jbParser 387 } // namespace jbParser
387 388
388 /** 389 /**
389 * This function parses the given filename and stores the results in the given 390 * This function parses the given filename and stores the results in the given
390 * families array. 391 * families array. Returns the version of the file, negative if the file does no t exist.
391 */ 392 */
392 static void parseConfigFile(const char* filename, SkTDArray<FontFamily*> &famili es) { 393 static int parse_config_file(const char* filename, SkTDArray<FontFamily*>& famil ies) {
393 394
394 FILE* file = fopen(filename, "r"); 395 FILE* file = fopen(filename, "r");
395 396
396 // Some of the files we attempt to parse (in particular, /vendor/etc/fallbac k_fonts.xml) 397 // Some of the files we attempt to parse (in particular, /vendor/etc/fallbac k_fonts.xml)
397 // are optional - failure here is okay because one of these optional files m ay not exist. 398 // are optional - failure here is okay because one of these optional files m ay not exist.
398 if (NULL == file) { 399 if (NULL == file) {
399 return; 400 return -1;
400 } 401 }
401 402
402 XML_Parser parser = XML_ParserCreate(NULL); 403 XML_Parser parser = XML_ParserCreate(NULL);
403 FamilyData familyData(parser, families); 404 FamilyData familyData(parser, families);
404 XML_SetUserData(parser, &familyData); 405 XML_SetUserData(parser, &familyData);
405 // Start parsing oldschool; switch these in flight if we detect a newer vers ion of the file. 406 // Start parsing oldschool; switch these in flight if we detect a newer vers ion of the file.
406 XML_SetElementHandler(parser, jbParser::startElementHandler, jbParser::endEl ementHandler); 407 XML_SetElementHandler(parser, jbParser::start_element_handler, jbParser::end _element_handler);
407 408
408 char buffer[512]; 409 char buffer[512];
409 bool done = false; 410 bool done = false;
410 while (!done) { 411 while (!done) {
411 fgets(buffer, sizeof(buffer), file); 412 fgets(buffer, sizeof(buffer), file);
412 size_t len = strlen(buffer); 413 size_t len = strlen(buffer);
413 if (feof(file) != 0) { 414 if (feof(file) != 0) {
414 done = true; 415 done = true;
415 } 416 }
416 XML_Parse(parser, buffer, len, done); 417 XML_Parse(parser, buffer, len, done);
417 } 418 }
418 XML_ParserFree(parser); 419 XML_ParserFree(parser);
419 fclose(file); 420 fclose(file);
421 return familyData.fVersion;
420 } 422 }
421 423
422 static void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { 424 /** Returns the version of the system font file actually found, negative if none . */
425 static int append_system_font_families(SkTDArray<FontFamily*>& fontFamilies) {
423 int initialCount = fontFamilies.count(); 426 int initialCount = fontFamilies.count();
424 parseConfigFile(LMP_SYSTEM_FONTS_FILE, fontFamilies); 427 int version = parse_config_file(LMP_SYSTEM_FONTS_FILE, fontFamilies);
425 428 if (version < 0 || fontFamilies.count() == initialCount) {
426 if (initialCount == fontFamilies.count()) { 429 version = parse_config_file(OLD_SYSTEM_FONTS_FILE, fontFamilies);
427 parseConfigFile(OLD_SYSTEM_FONTS_FILE, fontFamilies);
428 } 430 }
431 return version;
429 } 432 }
430 433
431 /** 434 /**
432 * In some versions of Android prior to Android 4.2 (JellyBean MR1 at API 435 * In some versions of Android prior to Android 4.2 (JellyBean MR1 at API
433 * Level 17) the fallback fonts for certain locales were encoded in their own 436 * Level 17) the fallback fonts for certain locales were encoded in their own
434 * XML files with a suffix that identified the locale. We search the provided 437 * XML files with a suffix that identified the locale. We search the provided
435 * directory for those files,add all of their entries to the fallback chain, and 438 * directory for those files,add all of their entries to the fallback chain, and
436 * include the locale as part of each entry. 439 * include the locale as part of each entry.
437 */ 440 */
438 static void getFallbackFontFamiliesForLocale(SkTDArray<FontFamily*> &fallbackFon ts, const char* dir) { 441 static void append_fallback_font_families_for_locale(SkTDArray<FontFamily*>& fal lbackFonts,
442 const char* dir)
443 {
439 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) 444 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
440 // The framework is beyond Android 4.2 and can therefore skip this function 445 // The framework is beyond Android 4.2 and can therefore skip this function
441 return; 446 return;
442 #endif 447 #endif
443 448
444 DIR* fontDirectory = opendir(dir); 449 DIR* fontDirectory = opendir(dir);
445 if (fontDirectory != NULL){ 450 if (fontDirectory != NULL){
446 struct dirent* dirEntry = readdir(fontDirectory); 451 struct dirent* dirEntry = readdir(fontDirectory);
447 while (dirEntry) { 452 while (dirEntry) {
448 453
449 // The size of both the prefix, suffix, and a minimum valid language code 454 // The size of both the prefix, suffix, and a minimum valid language code
450 static const size_t minSize = strlen(LOCALE_FALLBACK_FONTS_PREFIX) + 455 static const size_t minSize = strlen(LOCALE_FALLBACK_FONTS_PREFIX) +
451 strlen(LOCALE_FALLBACK_FONTS_SUFFIX) + 2; 456 strlen(LOCALE_FALLBACK_FONTS_SUFFIX) + 2;
452 457
453 SkString fileName(dirEntry->d_name); 458 SkString fileName(dirEntry->d_name);
454 if (fileName.size() >= minSize && 459 if (fileName.size() >= minSize &&
455 fileName.startsWith(LOCALE_FALLBACK_FONTS_PREFIX) && 460 fileName.startsWith(LOCALE_FALLBACK_FONTS_PREFIX) &&
456 fileName.endsWith(LOCALE_FALLBACK_FONTS_SUFFIX)) { 461 fileName.endsWith(LOCALE_FALLBACK_FONTS_SUFFIX)) {
457 462
458 static const size_t fixedLen = strlen(LOCALE_FALLBACK_FONTS_PREF IX) - 463 static const size_t fixedLen = strlen(LOCALE_FALLBACK_FONTS_PREF IX) -
459 strlen(LOCALE_FALLBACK_FONTS_SUFF IX); 464 strlen(LOCALE_FALLBACK_FONTS_SUFF IX);
460 465
461 SkString locale(fileName.c_str() - strlen(LOCALE_FALLBACK_FONTS_ PREFIX), 466 SkString locale(fileName.c_str() - strlen(LOCALE_FALLBACK_FONTS_ PREFIX),
462 fileName.size() - fixedLen); 467 fileName.size() - fixedLen);
463 468
464 SkString absoluteFilename; 469 SkString absoluteFilename;
465 absoluteFilename.printf("%s/%s", dir, fileName.c_str()); 470 absoluteFilename.printf("%s/%s", dir, fileName.c_str());
466 471
467 SkTDArray<FontFamily*> langSpecificFonts; 472 SkTDArray<FontFamily*> langSpecificFonts;
468 parseConfigFile(absoluteFilename.c_str(), langSpecificFonts); 473 parse_config_file(absoluteFilename.c_str(), langSpecificFonts);
469 474
470 for (int i = 0; i < langSpecificFonts.count(); ++i) { 475 for (int i = 0; i < langSpecificFonts.count(); ++i) {
471 FontFamily* family = langSpecificFonts[i]; 476 FontFamily* family = langSpecificFonts[i];
472 family->fLanguage = SkLanguage(locale); 477 family->fLanguage = SkLanguage(locale);
473 *fallbackFonts.append() = family; 478 *fallbackFonts.append() = family;
474 } 479 }
475 } 480 }
476 481
477 // proceed to the next entry in the directory 482 // proceed to the next entry in the directory
478 dirEntry = readdir(fontDirectory); 483 dirEntry = readdir(fontDirectory);
479 } 484 }
480 // cleanup the directory reference 485 // cleanup the directory reference
481 closedir(fontDirectory); 486 closedir(fontDirectory);
482 } 487 }
483 } 488 }
484 489
485 static void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) { 490 static void append_system_fallback_font_families(SkTDArray<FontFamily*>& fallbac kFonts) {
491 parse_config_file(FALLBACK_FONTS_FILE, fallbackFonts);
492 append_fallback_font_families_for_locale(fallbackFonts, LOCALE_FALLBACK_FONT S_SYSTEM_DIR);
493 }
494
495 static void mixin_vendor_fallback_font_families(SkTDArray<FontFamily*>& fallback Fonts) {
486 SkTDArray<FontFamily*> vendorFonts; 496 SkTDArray<FontFamily*> vendorFonts;
487 parseConfigFile(FALLBACK_FONTS_FILE, fallbackFonts); 497 parse_config_file(VENDOR_FONTS_FILE, vendorFonts);
488 parseConfigFile(VENDOR_FONTS_FILE, vendorFonts); 498 append_fallback_font_families_for_locale(vendorFonts, LOCALE_FALLBACK_FONTS_ VENDOR_DIR);
489
490 getFallbackFontFamiliesForLocale(fallbackFonts, LOCALE_FALLBACK_FONTS_SYSTEM _DIR);
491 getFallbackFontFamiliesForLocale(vendorFonts, LOCALE_FALLBACK_FONTS_VENDOR_D IR);
492 499
493 // This loop inserts the vendor fallback fonts in the correct order in the 500 // This loop inserts the vendor fallback fonts in the correct order in the
494 // overall fallbacks list. 501 // overall fallbacks list.
495 int currentOrder = -1; 502 int currentOrder = -1;
496 for (int i = 0; i < vendorFonts.count(); ++i) { 503 for (int i = 0; i < vendorFonts.count(); ++i) {
497 FontFamily* family = vendorFonts[i]; 504 FontFamily* family = vendorFonts[i];
498 int order = family->fOrder; 505 int order = family->fOrder;
499 if (order < 0) { 506 if (order < 0) {
500 if (currentOrder < 0) { 507 if (currentOrder < 0) {
501 // Default case - just add it to the end of the fallback list 508 // Default case - just add it to the end of the fallback list
502 *fallbackFonts.append() = family; 509 *fallbackFonts.append() = family;
503 } else { 510 } else {
504 // no order specified on this font, but we're incrementing the o rder 511 // no order specified on this font, but we're incrementing the o rder
505 // based on an earlier order insertion request 512 // based on an earlier order insertion request
506 *fallbackFonts.insert(currentOrder++) = family; 513 *fallbackFonts.insert(currentOrder++) = family;
507 } 514 }
508 } else { 515 } else {
509 // Add the font into the fallback list in the specified order. Set 516 // Add the font into the fallback list in the specified order. Set
510 // currentOrder for correct placement of other fonts in the vendor l ist. 517 // currentOrder for correct placement of other fonts in the vendor l ist.
511 *fallbackFonts.insert(order) = family; 518 *fallbackFonts.insert(order) = family;
512 currentOrder = order + 1; 519 currentOrder = order + 1;
513 } 520 }
514 } 521 }
515 } 522 }
516 523
517 /** 524 /**
518 * Loads data on font families from various expected configuration files. The 525 * Loads data on font families from various expected configuration files. The
519 * resulting data is returned in the given fontFamilies array. 526 * resulting data is returned in the given fontFamilies array.
520 */ 527 */
521 void SkFontConfigParser::GetFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { 528 void SkFontConfigParser::GetFontFamilies(SkTDArray<FontFamily*>& fontFamilies) {
522 529 // Version 21 of the system font configuration does not need any fallback co nfiguration files.
523 getSystemFontFamilies(fontFamilies); 530 if (append_system_font_families(fontFamilies) >= 21) {
531 return;
532 }
524 533
525 // Append all the fallback fonts to system fonts 534 // Append all the fallback fonts to system fonts
526 SkTDArray<FontFamily*> fallbackFonts; 535 SkTDArray<FontFamily*> fallbackFonts;
527 getFallbackFontFamilies(fallbackFonts); 536 append_system_fallback_font_families(fallbackFonts);
537 mixin_vendor_fallback_font_families(fallbackFonts);
528 for (int i = 0; i < fallbackFonts.count(); ++i) { 538 for (int i = 0; i < fallbackFonts.count(); ++i) {
529 fallbackFonts[i]->fIsFallbackFont = true; 539 fallbackFonts[i]->fIsFallbackFont = true;
530 *fontFamilies.append() = fallbackFonts[i]; 540 *fontFamilies.append() = fallbackFonts[i];
531 } 541 }
532 } 542 }
533 543
534 void SkFontConfigParser::GetTestFontFamilies(SkTDArray<FontFamily*> &fontFamilie s, 544 void SkFontConfigParser::GetTestFontFamilies(SkTDArray<FontFamily*>& fontFamilie s,
535 const char* testMainConfigFile, 545 const char* testMainConfigFile,
536 const char* testFallbackConfigFile) { 546 const char* testFallbackConfigFile) {
537 parseConfigFile(testMainConfigFile, fontFamilies); 547 parse_config_file(testMainConfigFile, fontFamilies);
538 548
539 SkTDArray<FontFamily*> fallbackFonts; 549 SkTDArray<FontFamily*> fallbackFonts;
540 if (testFallbackConfigFile) { 550 if (testFallbackConfigFile) {
541 parseConfigFile(testFallbackConfigFile, fallbackFonts); 551 parse_config_file(testFallbackConfigFile, fallbackFonts);
542 } 552 }
543 553
544 // Append all fallback fonts to system fonts 554 // Append all fallback fonts to system fonts
545 for (int i = 0; i < fallbackFonts.count(); ++i) { 555 for (int i = 0; i < fallbackFonts.count(); ++i) {
546 fallbackFonts[i]->fIsFallbackFont = true; 556 fallbackFonts[i]->fIsFallbackFont = true;
547 *fontFamilies.append() = fallbackFonts[i]; 557 *fontFamilies.append() = fallbackFonts[i];
548 } 558 }
549 } 559 }
550 560
551 SkLanguage SkLanguage::getParent() const { 561 SkLanguage SkLanguage::getParent() const {
552 SkASSERT(!fTag.isEmpty()); 562 SkASSERT(!fTag.isEmpty());
553 const char* tag = fTag.c_str(); 563 const char* tag = fTag.c_str();
554 564
555 // strip off the rightmost "-.*" 565 // strip off the rightmost "-.*"
556 const char* parentTagEnd = strrchr(tag, '-'); 566 const char* parentTagEnd = strrchr(tag, '-');
557 if (parentTagEnd == NULL) { 567 if (parentTagEnd == NULL) {
558 return SkLanguage(); 568 return SkLanguage();
559 } 569 }
560 size_t parentTagLen = parentTagEnd - tag; 570 size_t parentTagLen = parentTagEnd - tag;
561 return SkLanguage(tag, parentTagLen); 571 return SkLanguage(tag, parentTagLen);
562 } 572 }
OLDNEW
« no previous file with comments | « src/ports/SkFontConfigParser_android.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698