diff options
author | bungeman <bungeman@google.com> | 2015-02-11 07:18:51 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-11 07:18:51 -0800 |
commit | c3c694342ad393b88cee5885395f182082aa2ebb (patch) | |
tree | f1c6cd5128c1596ac15b4b9eb8c2e524706236c8 | |
parent | 02b05015b55d1900a9e34039942101da189053ce (diff) |
Fix append_fallback_font_families_for_locale.
The language was being set to garbage, now set to part of the file name.
Add a test to ensure we continue to parse fallback directories correctly.
BUG=chromium:422180
Review URL: https://codereview.chromium.org/912053003
-rw-r--r-- | include/core/SkTemplates.h | 4 | ||||
-rw-r--r-- | resources/android_fonts/v17/fallback_fonts-ja.xml | 112 | ||||
-rw-r--r-- | src/ports/SkFontConfigParser_android.cpp | 68 | ||||
-rw-r--r-- | src/ports/SkFontConfigParser_android.h | 3 | ||||
-rw-r--r-- | tests/FontConfigParser.cpp | 27 |
5 files changed, 178 insertions, 36 deletions
diff --git a/include/core/SkTemplates.h b/include/core/SkTemplates.h index 6ab44394d8..c26e4422b5 100644 --- a/include/core/SkTemplates.h +++ b/include/core/SkTemplates.h @@ -107,6 +107,10 @@ template <typename T, int (*P)(T*)> class SkAutoTCallIProc : SkNoncopyable { public: SkAutoTCallIProc(T* obj): fObj(obj) {} ~SkAutoTCallIProc() { if (fObj) P(fObj); } + + operator T*() const { return fObj; } + T* operator->() const { SkASSERT(fObj); return fObj; } + T* detach() { T* obj = fObj; fObj = NULL; return obj; } private: T* fObj; diff --git a/resources/android_fonts/v17/fallback_fonts-ja.xml b/resources/android_fonts/v17/fallback_fonts-ja.xml new file mode 100644 index 0000000000..5f9b5ed948 --- /dev/null +++ b/resources/android_fonts/v17/fallback_fonts-ja.xml @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Fallback Fonts + + This file specifies the fonts, and the priority order, that will be searched for any + glyphs not handled by the default fonts specified in /system/etc/system_fonts.xml. + Each entry consists of a family tag and a list of files (file names) which support that + family. The fonts for each family are listed in the order of the styles that they + handle (the order is: regular, bold, italic, and bold-italic). The order in which the + families are listed in this file represents the order in which these fallback fonts + will be searched for glyphs that are not supported by the default system fonts (which are + found in /system/etc/system_fonts.xml). + + Note that there is not nameset for fallback fonts, unlike the fonts specified in + system_fonts.xml. The ability to support specific names in fallback fonts may be supported + in the future. For now, the lack of files entries here is an indicator to the system that + these are fallback fonts, instead of default named system fonts. + + There is another optional file in /vendor/etc/fallback_fonts.xml. That file can be used to + provide references to other font families that should be used in addition to the default + fallback fonts. That file can also specify the order in which the fallback fonts should be + searched, to ensure that a vendor-provided font will be used before another fallback font + which happens to handle the same glyph. + + Han languages (Chinese, Japanese, and Korean) share a common range of unicode characters; + their ordering in the fallback or vendor files gives priority to the first in the list. + Locale-specific ordering can be configured by adding language and region codes to the end + of the filename (e.g. /system/etc/fallback_fonts-ja.xml). When no region code is used, + as with this example, all regions are matched. Use separate files for each supported locale. + The standard fallback file (fallback_fonts.xml) is used when a locale does not have its own + file. All fallback files must contain the same complete set of fonts; only their ordering + can differ. +--> +<familyset> + <family> + <fileset> + <file>DroidNaskh-Regular-SystemUI.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>DroidSansEthiopic-Regular.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>DroidSansHebrew-Regular.ttf</file> + <file>DroidSansHebrew-Bold.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>DroidSansThai.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>DroidSansArmenian.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>DroidSansGeorgian.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>DroidSansDevanagari-Regular.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>DroidSansTamil-Regular.ttf</file> + <file>DroidSansTamil-Bold.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>AnjaliNewLipi-light.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>Lohit-Bengali.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>Lohit-Kannada.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>Lohit-Telugu.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>AndroidEmoji.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>MTLmr3m.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>DroidSansFallback.ttf</file> + </fileset> + </family> +</familyset> diff --git a/src/ports/SkFontConfigParser_android.cpp b/src/ports/SkFontConfigParser_android.cpp index 20fee40a78..ce4ebbeb41 100644 --- a/src/ports/SkFontConfigParser_android.cpp +++ b/src/ports/SkFontConfigParser_android.cpp @@ -502,44 +502,42 @@ static void append_fallback_font_families_for_locale(SkTDArray<FontFamily*>& fal return; #endif - DIR* fontDirectory = opendir(dir); - if (fontDirectory != NULL){ - struct dirent* dirEntry = readdir(fontDirectory); - while (dirEntry) { - - // The size of both the prefix, suffix, and a minimum valid language code - static const size_t minSize = strlen(LOCALE_FALLBACK_FONTS_PREFIX) + - strlen(LOCALE_FALLBACK_FONTS_SUFFIX) + 2; - - SkString fileName(dirEntry->d_name); - if (fileName.size() >= minSize && - fileName.startsWith(LOCALE_FALLBACK_FONTS_PREFIX) && - fileName.endsWith(LOCALE_FALLBACK_FONTS_SUFFIX)) { + SkAutoTCallIProc<DIR, closedir> fontDirectory(opendir(dir)); + if (NULL == fontDirectory) { + return; + } - static const size_t fixedLen = strlen(LOCALE_FALLBACK_FONTS_PREFIX) - - strlen(LOCALE_FALLBACK_FONTS_SUFFIX); + for (struct dirent* dirEntry; (dirEntry = readdir(fontDirectory));) { + // The size of both the prefix, suffix, and a minimum valid language code + static const size_t minSize = sizeof(LOCALE_FALLBACK_FONTS_PREFIX) - 1 + + sizeof(LOCALE_FALLBACK_FONTS_SUFFIX) - 1 + + 2; + + SkString fileName(dirEntry->d_name); + if (fileName.size() < minSize || + !fileName.startsWith(LOCALE_FALLBACK_FONTS_PREFIX) || + !fileName.endsWith(LOCALE_FALLBACK_FONTS_SUFFIX)) + { + continue; + } - SkString locale(fileName.c_str() - strlen(LOCALE_FALLBACK_FONTS_PREFIX), - fileName.size() - fixedLen); + static const size_t fixedLen = sizeof(LOCALE_FALLBACK_FONTS_PREFIX) - 1 + + sizeof(LOCALE_FALLBACK_FONTS_SUFFIX) - 1; - SkString absoluteFilename; - absoluteFilename.printf("%s/%s", dir, fileName.c_str()); + SkString locale(fileName.c_str() + sizeof(LOCALE_FALLBACK_FONTS_PREFIX) - 1, + fileName.size() - fixedLen); - SkTDArray<FontFamily*> langSpecificFonts; - parse_config_file(absoluteFilename.c_str(), langSpecificFonts, basePath, true); + SkString absoluteFilename; + absoluteFilename.printf("%s/%s", dir, fileName.c_str()); - for (int i = 0; i < langSpecificFonts.count(); ++i) { - FontFamily* family = langSpecificFonts[i]; - family->fLanguage = SkLanguage(locale); - *fallbackFonts.append() = family; - } - } + SkTDArray<FontFamily*> langSpecificFonts; + parse_config_file(absoluteFilename.c_str(), langSpecificFonts, basePath, true); - // proceed to the next entry in the directory - dirEntry = readdir(fontDirectory); + for (int i = 0; i < langSpecificFonts.count(); ++i) { + FontFamily* family = langSpecificFonts[i]; + family->fLanguage = SkLanguage(locale); + *fallbackFonts.append() = family; } - // cleanup the directory reference - closedir(fontDirectory); } } @@ -604,7 +602,8 @@ void SkFontConfigParser::GetSystemFontFamilies(SkTDArray<FontFamily*>& fontFamil void SkFontConfigParser::GetCustomFontFamilies(SkTDArray<FontFamily*>& fontFamilies, const SkString& basePath, const char* fontsXml, - const char* fallbackFontsXml) + const char* fallbackFontsXml, + const char* langFallbackFontsDir) { if (fontsXml) { parse_config_file(fontsXml, fontFamilies, basePath, false); @@ -612,6 +611,11 @@ void SkFontConfigParser::GetCustomFontFamilies(SkTDArray<FontFamily*>& fontFamil if (fallbackFontsXml) { parse_config_file(fallbackFontsXml, fontFamilies, basePath, true); } + if (langFallbackFontsDir) { + append_fallback_font_families_for_locale(fontFamilies, + langFallbackFontsDir, + basePath); + } } SkLanguage SkLanguage::getParent() const { diff --git a/src/ports/SkFontConfigParser_android.h b/src/ports/SkFontConfigParser_android.h index d77ca15e7a..2302c7712e 100644 --- a/src/ports/SkFontConfigParser_android.h +++ b/src/ports/SkFontConfigParser_android.h @@ -101,7 +101,8 @@ void GetSystemFontFamilies(SkTDArray<FontFamily*>& fontFamilies); void GetCustomFontFamilies(SkTDArray<FontFamily*>& fontFamilies, const SkString& basePath, const char* fontsXml, - const char* fallbackFontsXml); + const char* fallbackFontsXml, + const char* langFallbackFontsDir = NULL); } // SkFontConfigParser namespace diff --git a/tests/FontConfigParser.cpp b/tests/FontConfigParser.cpp index dfc8093f2a..dc1fac0547 100644 --- a/tests/FontConfigParser.cpp +++ b/tests/FontConfigParser.cpp @@ -22,6 +22,16 @@ int CountFallbacks(SkTDArray<FontFamily*> fontFamilies) { return countOfFallbackFonts; } +//https://tools.ietf.org/html/rfc5234#appendix-B.1 +static bool isALPHA(int c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); +} + +//https://tools.ietf.org/html/rfc5234#appendix-B.1 +static bool isDIGIT(int c) { + return ('0' <= c && c <= '9'); +} + void ValidateLoadedFonts(SkTDArray<FontFamily*> fontFamilies, const char* firstExpectedFile, skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, fontFamilies[0]->fNames.count() == 5); @@ -29,6 +39,15 @@ void ValidateLoadedFonts(SkTDArray<FontFamily*> fontFamilies, const char* firstE REPORTER_ASSERT(reporter, !strcmp(fontFamilies[0]->fFonts[0].fFileName.c_str(), firstExpectedFile)); REPORTER_ASSERT(reporter, !fontFamilies[0]->fIsFallbackFont); + + // Check that the languages are all sane. + for (int i = 0; i < fontFamilies.count(); ++i) { + const SkString& lang = fontFamilies[i]->fLanguage.getTag(); + for (size_t j = 0; j < lang.size(); ++j) { + int c = lang[j]; + REPORTER_ASSERT(reporter, isALPHA(c) || isDIGIT(c) || '-' == c); + } + } } void DumpLoadedFonts(SkTDArray<FontFamily*> fontFamilies) { @@ -55,6 +74,7 @@ void DumpLoadedFonts(SkTDArray<FontFamily*> fontFamilies) { SkDebugf(" file (%d) %s#%d\n", ffi.fWeight, ffi.fFileName.c_str(), ffi.fIndex); } } + SkDebugf("\n\n"); } DEF_TEST(FontConfigParserAndroid, reporter) { @@ -82,11 +102,12 @@ DEF_TEST(FontConfigParserAndroid, reporter) { SkFontConfigParser::GetCustomFontFamilies(v17FontFamilies, SkString("/custom/font/path/"), GetResourcePath("android_fonts/v17/system_fonts.xml").c_str(), - GetResourcePath("android_fonts/v17/fallback_fonts.xml").c_str()); + GetResourcePath("android_fonts/v17/fallback_fonts.xml").c_str(), + GetResourcePath("android_fonts/v17").c_str()); if (v17FontFamilies.count() > 0) { - REPORTER_ASSERT(reporter, v17FontFamilies.count() == 41); - REPORTER_ASSERT(reporter, CountFallbacks(v17FontFamilies) == 31); + REPORTER_ASSERT(reporter, v17FontFamilies.count() == 56); + REPORTER_ASSERT(reporter, CountFallbacks(v17FontFamilies) == 46); DumpLoadedFonts(v17FontFamilies); ValidateLoadedFonts(v17FontFamilies, "Roboto-Regular.ttf", reporter); |