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 |