aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bungeman <bungeman@google.com>2015-02-11 07:18:51 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-02-11 07:18:51 -0800
commitc3c694342ad393b88cee5885395f182082aa2ebb (patch)
treef1c6cd5128c1596ac15b4b9eb8c2e524706236c8
parent02b05015b55d1900a9e34039942101da189053ce (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.h4
-rw-r--r--resources/android_fonts/v17/fallback_fonts-ja.xml112
-rw-r--r--src/ports/SkFontConfigParser_android.cpp68
-rw-r--r--src/ports/SkFontConfigParser_android.h3
-rw-r--r--tests/FontConfigParser.cpp27
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);