Chromium Code Reviews| 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 "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 <stdio.h> | 15 #include <stdio.h> |
| 15 #include <sys/system_properties.h> | |
| 16 | 16 |
| 17 #include <limits> | 17 #include <limits> |
| 18 | 18 |
| 19 #define SYSTEM_FONTS_FILE "/system/etc/system_fonts.xml" | 19 #define SYSTEM_FONTS_FILE "/system/etc/system_fonts.xml" |
| 20 #define FALLBACK_FONTS_FILE "/system/etc/fallback_fonts.xml" | 20 #define FALLBACK_FONTS_FILE "/system/etc/fallback_fonts.xml" |
| 21 #define VENDOR_FONTS_FILE "/vendor/etc/fallback_fonts.xml" | 21 #define VENDOR_FONTS_FILE "/vendor/etc/fallback_fonts.xml" |
| 22 | 22 |
| 23 #define LOCALE_FALLBACK_FONTS_DIR "/system/etc" | |
| 24 #define LOCALE_FALLBACK_FONTS_PREFIX "fallback_fonts-" | |
| 25 #define LOCALE_FALLBACK_FONTS_SUFFIX ".xml" | |
| 26 | |
| 23 // These defines are used to determine the kind of tag that we're currently | 27 // These defines are used to determine the kind of tag that we're currently |
| 24 // populating with data. We only care about the sibling tags nameset and fileset | 28 // populating with data. We only care about the sibling tags nameset and fileset |
| 25 // for now. | 29 // for now. |
| 26 #define NO_TAG 0 | 30 #define NO_TAG 0 |
| 27 #define NAMESET_TAG 1 | 31 #define NAMESET_TAG 1 |
| 28 #define FILESET_TAG 2 | 32 #define FILESET_TAG 2 |
| 29 | 33 |
| 30 /** | 34 /** |
| 31 * The FamilyData structure is passed around by the parser so that each handler | 35 * The FamilyData structure is passed around by the parser so that each handler |
| 32 * can read these variables that are relevant to the current parsing. | 36 * can read these variables that are relevant to the current parsing. |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 XML_SetCharacterDataHandler(*familyData->parser, NULL); | 191 XML_SetCharacterDataHandler(*familyData->parser, NULL); |
| 188 } | 192 } |
| 189 } | 193 } |
| 190 | 194 |
| 191 /** | 195 /** |
| 192 * This function parses the given filename and stores the results in the given | 196 * This function parses the given filename and stores the results in the given |
| 193 * families array. | 197 * families array. |
| 194 */ | 198 */ |
| 195 static void parseConfigFile(const char *filename, SkTDArray<FontFamily*> &famili es) { | 199 static void parseConfigFile(const char *filename, SkTDArray<FontFamily*> &famili es) { |
| 196 | 200 |
| 197 FILE* file = NULL; | 201 FILE* file = fopen(filename, "r"); |
| 198 | |
| 199 #if !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) | |
| 200 // if we are using a version of Android prior to Android 4.2 (JellyBean MR1 | |
| 201 // at API Level 17) then we need to look for files with a different suffix. | |
| 202 char sdkVersion[PROP_VALUE_MAX]; | |
| 203 __system_property_get("ro.build.version.sdk", sdkVersion); | |
| 204 const int sdkVersionInt = atoi(sdkVersion); | |
| 205 | |
| 206 if (0 != *sdkVersion && sdkVersionInt < 17) { | |
| 207 SkString basename; | |
| 208 SkString updatedFilename; | |
| 209 SkString locale = SkFontConfigParser::GetLocale(); | |
| 210 | |
| 211 basename.set(filename); | |
| 212 // Remove the .xml suffix. We'll add it back in a moment. | |
| 213 if (basename.endsWith(".xml")) { | |
| 214 basename.resize(basename.size()-4); | |
| 215 } | |
| 216 // Try first with language and region | |
| 217 updatedFilename.printf("%s-%s.xml", basename.c_str(), locale.c_str()); | |
| 218 file = fopen(updatedFilename.c_str(), "r"); | |
| 219 if (!file) { | |
| 220 // If not found, try next with just language | |
| 221 updatedFilename.printf("%s-%.2s.xml", basename.c_str(), locale.c_str ()); | |
| 222 file = fopen(updatedFilename.c_str(), "r"); | |
| 223 } | |
| 224 } | |
| 225 #endif | |
| 226 | |
| 227 if (NULL == file) { | |
| 228 file = fopen(filename, "r"); | |
| 229 } | |
| 230 | 202 |
| 231 // Some of the files we attempt to parse (in particular, /vendor/etc/fallbac k_fonts.xml) | 203 // Some of the files we attempt to parse (in particular, /vendor/etc/fallbac k_fonts.xml) |
| 232 // are optional - failure here is okay because one of these optional files m ay not exist. | 204 // are optional - failure here is okay because one of these optional files m ay not exist. |
| 233 if (NULL == file) { | 205 if (NULL == file) { |
| 234 return; | 206 return; |
| 235 } | 207 } |
| 236 | 208 |
| 237 XML_Parser parser = XML_ParserCreate(NULL); | 209 XML_Parser parser = XML_ParserCreate(NULL); |
| 238 FamilyData *familyData = new FamilyData(&parser, families); | 210 FamilyData *familyData = new FamilyData(&parser, families); |
| 239 XML_SetUserData(parser, familyData); | 211 XML_SetUserData(parser, familyData); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 255 | 227 |
| 256 static void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { | 228 static void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { |
| 257 parseConfigFile(SYSTEM_FONTS_FILE, fontFamilies); | 229 parseConfigFile(SYSTEM_FONTS_FILE, fontFamilies); |
| 258 } | 230 } |
| 259 | 231 |
| 260 static void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) { | 232 static void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) { |
| 261 SkTDArray<FontFamily*> vendorFonts; | 233 SkTDArray<FontFamily*> vendorFonts; |
| 262 parseConfigFile(FALLBACK_FONTS_FILE, fallbackFonts); | 234 parseConfigFile(FALLBACK_FONTS_FILE, fallbackFonts); |
| 263 parseConfigFile(VENDOR_FONTS_FILE, vendorFonts); | 235 parseConfigFile(VENDOR_FONTS_FILE, vendorFonts); |
| 264 | 236 |
| 237 #if !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) | |
| 238 // In some versions of Android prior to Android 4.2 (JellyBean MR1 at API | |
| 239 // Level 17) the fallback fonts for certain locales were encoded in their | |
| 240 // own XML files with a suffix that identified the locale. We search the | |
| 241 // system for those files and add all of their entries to the fallback chain | |
| 242 // including the locale in the entry. | |
| 243 | |
| 244 DIR* fontDirectory = opendir(LOCALE_FALLBACK_FONTS_DIR); | |
| 245 if (fontDirectory != NULL){ | |
| 246 struct dirent* dirEntry = readdir(fontDirectory); | |
| 247 while (dirEntry){ | |
|
bungeman-skia
2014/08/01 20:41:25
nit: space after ')'
djsollen
2014/08/04 14:18:26
Done.
| |
| 248 | |
| 249 // The size of both the prefix, suffix, and a minimum valid language code | |
| 250 const int minSize = strlen(LOCALE_FALLBACK_FONTS_PREFIX) + | |
|
djsollen
2014/08/01 20:13:41
it appears that both fallback_fonts-**.xml and ven
| |
| 251 strlen(LOCALE_FALLBACK_FONTS_SUFFIX) + 2; | |
| 252 | |
| 253 SkString fileName(dirEntry->d_name); | |
| 254 if (fileName.startsWith(LOCALE_FALLBACK_FONTS_PREFIX) && fileName.si ze() >= minSize) { | |
|
bungeman-skia
2014/08/01 20:41:25
Do we care to check here if is does end with the S
djsollen
2014/08/04 14:18:26
Added suffix checks
| |
| 255 | |
| 256 SkString locale(fileName); | |
|
bungeman-skia
2014/08/01 20:41:24
Can this be something like
int localeLen = strlen
djsollen
2014/08/04 14:18:26
Done.
| |
| 257 locale.resize(fileName.size() - strlen(LOCALE_FALLBACK_FONTS_SUF FIX)); | |
|
bungeman-skia
2014/08/01 20:41:25
Well, I was going to say replace "strlen(CONST_STR
| |
| 258 locale.remove(0, strlen(LOCALE_FALLBACK_FONTS_PREFIX)); | |
| 259 | |
| 260 SkString absoluteFilename; | |
| 261 absoluteFilename.printf("%s/%s", LOCALE_FALLBACK_FONTS_DIR, file Name.c_str()); | |
| 262 | |
| 263 SkTDArray<FontFamily*> langSpecificFonts; | |
| 264 parseConfigFile(absoluteFilename.c_str(), langSpecificFonts); | |
| 265 | |
| 266 for (int i = 0; i < langSpecificFonts.count(); ++i) { | |
| 267 FontFamily* family = langSpecificFonts[i]; | |
| 268 for (int j = 0; j < family->fFontFiles.count(); ++j) { | |
| 269 family->fFontFiles[j].fPaintOptions.setLanguage(locale); | |
| 270 } | |
| 271 *fallbackFonts.append() = family; | |
| 272 } | |
| 273 } | |
| 274 | |
| 275 // proceed to the next entry in the directory | |
| 276 dirEntry = readdir(fontDirectory); | |
| 277 } | |
| 278 } | |
| 279 #endif | |
| 280 | |
| 265 // This loop inserts the vendor fallback fonts in the correct order in the | 281 // This loop inserts the vendor fallback fonts in the correct order in the |
| 266 // overall fallbacks list. | 282 // overall fallbacks list. |
| 267 int currentOrder = -1; | 283 int currentOrder = -1; |
| 268 for (int i = 0; i < vendorFonts.count(); ++i) { | 284 for (int i = 0; i < vendorFonts.count(); ++i) { |
| 269 FontFamily* family = vendorFonts[i]; | 285 FontFamily* family = vendorFonts[i]; |
| 270 int order = family->order; | 286 int order = family->order; |
| 271 if (order < 0) { | 287 if (order < 0) { |
| 272 if (currentOrder < 0) { | 288 if (currentOrder < 0) { |
| 273 // Default case - just add it to the end of the fallback list | 289 // Default case - just add it to the end of the fallback list |
| 274 *fallbackFonts.append() = family; | 290 *fallbackFonts.append() = family; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 | 326 |
| 311 SkTDArray<FontFamily*> fallbackFonts; | 327 SkTDArray<FontFamily*> fallbackFonts; |
| 312 parseConfigFile(testFallbackConfigFile, fallbackFonts); | 328 parseConfigFile(testFallbackConfigFile, fallbackFonts); |
| 313 | 329 |
| 314 // Append all fallback fonts to system fonts | 330 // Append all fallback fonts to system fonts |
| 315 for (int i = 0; i < fallbackFonts.count(); ++i) { | 331 for (int i = 0; i < fallbackFonts.count(); ++i) { |
| 316 fallbackFonts[i]->fIsFallbackFont = true; | 332 fallbackFonts[i]->fIsFallbackFont = true; |
| 317 *fontFamilies.append() = fallbackFonts[i]; | 333 *fontFamilies.append() = fallbackFonts[i]; |
| 318 } | 334 } |
| 319 } | 335 } |
| 320 | |
| 321 /** | |
| 322 * Read the persistent locale. | |
| 323 */ | |
| 324 SkString SkFontConfigParser::GetLocale() | |
| 325 { | |
| 326 char propLang[PROP_VALUE_MAX], propRegn[PROP_VALUE_MAX]; | |
| 327 __system_property_get("persist.sys.language", propLang); | |
| 328 __system_property_get("persist.sys.country", propRegn); | |
| 329 | |
| 330 if (*propLang == 0 && *propRegn == 0) { | |
| 331 /* Set to ro properties, default is en_US */ | |
| 332 __system_property_get("ro.product.locale.language", propLang); | |
| 333 __system_property_get("ro.product.locale.region", propRegn); | |
| 334 if (*propLang == 0 && *propRegn == 0) { | |
| 335 strcpy(propLang, "en"); | |
| 336 strcpy(propRegn, "US"); | |
| 337 } | |
| 338 } | |
| 339 | |
| 340 SkString locale(6); | |
| 341 char* localeCStr = locale.writable_str(); | |
| 342 | |
| 343 strncpy(localeCStr, propLang, 2); | |
| 344 localeCStr[2] = '-'; | |
| 345 strncpy(&localeCStr[3], propRegn, 2); | |
| 346 localeCStr[5] = '\0'; | |
| 347 | |
| 348 return locale; | |
| 349 } | |
| OLD | NEW |