aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ports
diff options
context:
space:
mode:
authorGravatar djsollen@google.com <djsollen@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-03-21 15:39:03 +0000
committerGravatar djsollen@google.com <djsollen@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-03-21 15:39:03 +0000
commite63793a2c8d2871bf7d95195be7b93ff669688d7 (patch)
tree5b3f833f7cbb71470a9e2aba50e8dc7b2078e04b /src/ports
parent0ffc56f6745e3c5d9a9baa15a3259da5fea0f88a (diff)
Upstream changes from Android repository.
Review URL: https://codereview.appspot.com/5752055 git-svn-id: http://skia.googlecode.com/svn/trunk@3449 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/ports')
-rw-r--r--src/ports/FontHostConfiguration_android.cpp90
-rw-r--r--src/ports/FontHostConfiguration_android.h17
-rw-r--r--src/ports/SkFontHost_android.cpp132
3 files changed, 222 insertions, 17 deletions
diff --git a/src/ports/FontHostConfiguration_android.cpp b/src/ports/FontHostConfiguration_android.cpp
index 475dc4af8b..d1164c800d 100644
--- a/src/ports/FontHostConfiguration_android.cpp
+++ b/src/ports/FontHostConfiguration_android.cpp
@@ -16,8 +16,12 @@
*/
#include "FontHostConfiguration_android.h"
-#include <expat.h>
+#include "SkString.h"
#include "SkTDArray.h"
+#include <expat.h>
+#if !defined(SK_BUILD_FOR_ANDROID_NDK)
+ #include <cutils/properties.h>
+#endif
#define SYSTEM_FONTS_FILE "/system/etc/system_fonts.xml"
#define FALLBACK_FONTS_FILE "/system/etc/fallback_fonts.xml"
@@ -127,6 +131,65 @@ void endElementHandler(void *data, const char *tag) {
}
}
+#if !defined(SK_BUILD_FOR_ANDROID_NDK)
+/**
+ * Read the persistent locale.
+ */
+void getLocale(char* language, char* region)
+{
+ char propLang[PROPERTY_VALUE_MAX], propRegn[PROPERTY_VALUE_MAX];
+
+ property_get("persist.sys.language", propLang, "");
+ property_get("persist.sys.country", propRegn, "");
+ if (*propLang == 0 && *propRegn == 0) {
+ /* Set to ro properties, default is en_US */
+ property_get("ro.product.locale.language", propLang, "en");
+ property_get("ro.product.locale.region", propRegn, "US");
+ }
+ strncat(language, propLang, 2);
+ strncat(region, propRegn, 2);
+}
+#endif
+
+/**
+ * Use the current system locale (language and region) to open the best matching
+ * customization. For example, when the language is Japanese, the sequence might be:
+ * /system/etc/fallback_fonts-ja-JP.xml
+ * /system/etc/fallback_fonts-ja.xml
+ * /system/etc/fallback_fonts.xml
+ */
+FILE* openLocalizedFile(const char* origname) {
+ FILE* file = 0;
+
+#if !defined(SK_BUILD_FOR_ANDROID_NDK)
+ SkString basename;
+ SkString filename;
+ char language[3] = "";
+ char region[3] = "";
+
+ basename.set(origname);
+ // Remove the .xml suffix. We'll add it back in a moment.
+ if (basename.endsWith(".xml")) {
+ basename.resize(basename.size()-4);
+ }
+ getLocale(language, region);
+ // Try first with language and region
+ filename.printf("%s-%s-%s.xml", basename.c_str(), language, region);
+ file = fopen(filename.c_str(), "r");
+ if (!file) {
+ // If not found, try next with just language
+ filename.printf("%s-%s.xml", basename.c_str(), language);
+ file = fopen(filename.c_str(), "r");
+ }
+#endif
+
+ if (!file) {
+ // If still not found, try just the original name
+ file = fopen(origname, "r");
+ }
+ return file;
+}
+
/**
* This function parses the given filename and stores the results in the given
* families array.
@@ -136,7 +199,7 @@ void parseConfigFile(const char *filename, SkTDArray<FontFamily*> &families) {
FamilyData *familyData = new FamilyData(&parser, families);
XML_SetUserData(parser, familyData);
XML_SetElementHandler(parser, startElementHandler, endElementHandler);
- FILE *file = fopen(filename, "r");
+ FILE *file = openLocalizedFile(filename);
// Some of the files we attempt to parse (in particular, /vendor/etc/fallback_fonts.xml)
// are optional - failure here is okay because one of these optional files may not exist.
if (file == NULL) {
@@ -154,15 +217,12 @@ void parseConfigFile(const char *filename, SkTDArray<FontFamily*> &families) {
}
}
-/**
- * Loads data on font families from various expected configuration files. The
- * resulting data is returned in the given fontFamilies array.
- */
-void getFontFamilies(SkTDArray<FontFamily*> &fontFamilies) {
+void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) {
+ parseConfigFile(SYSTEM_FONTS_FILE, fontFamilies);
+}
- SkTDArray<FontFamily*> fallbackFonts;
+void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) {
SkTDArray<FontFamily*> vendorFonts;
- parseConfigFile(SYSTEM_FONTS_FILE, fontFamilies);
parseConfigFile(FALLBACK_FONTS_FILE, fallbackFonts);
parseConfigFile(VENDOR_FONTS_FILE, vendorFonts);
@@ -188,6 +248,18 @@ void getFontFamilies(SkTDArray<FontFamily*> &fontFamilies) {
currentOrder = order + 1;
}
}
+}
+
+/**
+ * Loads data on font families from various expected configuration files. The
+ * resulting data is returned in the given fontFamilies array.
+ */
+void getFontFamilies(SkTDArray<FontFamily*> &fontFamilies) {
+ SkTDArray<FontFamily*> fallbackFonts;
+
+ getSystemFontFamilies(fontFamilies);
+ getFallbackFontFamilies(fallbackFonts);
+
// Append all fallback fonts to system fonts
for (int i = 0; i < fallbackFonts.count(); ++i) {
*fontFamilies.append() = fallbackFonts[i];
diff --git a/src/ports/FontHostConfiguration_android.h b/src/ports/FontHostConfiguration_android.h
index 010f0efc0f..2441f0e436 100644
--- a/src/ports/FontHostConfiguration_android.h
+++ b/src/ports/FontHostConfiguration_android.h
@@ -39,4 +39,21 @@ struct FontFamily {
*/
void getFontFamilies(SkTDArray<FontFamily*> &fontFamilies);
+/**
+ * Parse only the core system font configuration file and return the results in
+ * an array of FontFamily structures.
+ */
+void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies);
+
+
+/**
+ * Parse the fallback and vendor system font configuration files and return the
+ * results in an array of FontFamily structures.
+ */
+void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts);
+
+#if !defined(SK_BUILD_FOR_ANDROID_NDK)
+ void getLocale(char* language, char* region);
+#endif
+
#endif /* FONTHOSTCONFIGURATION_ANDROID_H_ */
diff --git a/src/ports/SkFontHost_android.cpp b/src/ports/SkFontHost_android.cpp
index 4da17deeb5..edbc0169af 100644
--- a/src/ports/SkFontHost_android.cpp
+++ b/src/ports/SkFontHost_android.cpp
@@ -16,6 +16,7 @@
*/
#include "SkFontHost.h"
+#include "SkGraphics.h"
#include "SkDescriptor.h"
#include "SkMMapStream.h"
#include "SkPaint.h"
@@ -26,6 +27,7 @@
#include "SkTypeface_android.h"
#include "FontHostConfiguration_android.h"
#include <stdio.h>
+#include <string.h>
#define FONT_CACHE_MEMORY_BUDGET (768 * 1024)
@@ -73,6 +75,7 @@ static int32_t gUniqueFontID;
// this is the mutex that protects gFamilyHead and GetNameList()
SK_DECLARE_STATIC_MUTEX(gFamilyHeadAndNameListMutex);
static FamilyRec* gFamilyHead;
+static SkTDArray<NameFamilyPair> gFallbackFilenameList;
static NameFamilyPairList& GetNameList() {
/*
@@ -265,7 +268,6 @@ public:
: SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) {
fIsSysFont = sysFont;
-
// our caller has acquired the gFamilyHeadAndNameListMutex so this is safe
FamilyRec* rec = NULL;
if (familyMember) {
@@ -439,8 +441,6 @@ static const struct {
static FontInitRec *gSystemFonts;
static size_t gNumSystemFonts = 0;
-#define SYSTEM_FONTS_FILE "/system/etc/system_fonts.cfg"
-
// these globals are assigned (once) by load_system_fonts()
static FamilyRec* gDefaultFamily;
static SkTypeface* gDefaultNormal;
@@ -448,10 +448,66 @@ static char** gDefaultNames = NULL;
static uint32_t *gFallbackFonts;
static uint32_t *gFallbackScriptsMap;
+static void dump_globals() {
+ SkDebugf("gDefaultNormal=%p id=%u refCnt=%d", gDefaultNormal,
+ gDefaultNormal ? gDefaultNormal->uniqueID() : 0,
+ gDefaultNormal ? gDefaultNormal->getRefCnt() : 0);
+
+ if (gDefaultFamily) {
+ SkDebugf("gDefaultFamily=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}",
+ gDefaultFamily,
+ gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->uniqueID() : 0,
+ gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->uniqueID() : 0,
+ gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->uniqueID() : 0,
+ gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->uniqueID() : 0,
+ gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->getRefCnt() : 0,
+ gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->getRefCnt() : 0,
+ gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->getRefCnt() : 0,
+ gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->getRefCnt() : 0);
+ } else {
+ SkDebugf("gDefaultFamily=%p", gDefaultFamily);
+ }
+
+ SkDebugf("gNumSystemFonts=%d gSystemFonts=%p gFallbackFonts=%p",
+ gNumSystemFonts, gSystemFonts, gFallbackFonts);
+
+ for (size_t i = 0; i < gNumSystemFonts; ++i) {
+ SkDebugf("gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName);
+ size_t namesIndex = 0;
+ if (gSystemFonts[i].fNames)
+ for (const char* fontName = gSystemFonts[i].fNames[namesIndex];
+ fontName != 0;
+ fontName = gSystemFonts[i].fNames[++namesIndex]) {
+ SkDebugf(" name[%u]=%s", namesIndex, fontName);
+ }
+ }
+
+ if (gFamilyHead) {
+ FamilyRec* rec = gFamilyHead;
+ int i=0;
+ while (rec) {
+ SkDebugf("gFamilyHead[%d]=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}",
+ i++, rec,
+ rec->fFaces[0] ? rec->fFaces[0]->uniqueID() : 0,
+ rec->fFaces[1] ? rec->fFaces[1]->uniqueID() : 0,
+ rec->fFaces[2] ? rec->fFaces[2]->uniqueID() : 0,
+ rec->fFaces[3] ? rec->fFaces[3]->uniqueID() : 0,
+ rec->fFaces[0] ? rec->fFaces[0]->getRefCnt() : 0,
+ rec->fFaces[1] ? rec->fFaces[1]->getRefCnt() : 0,
+ rec->fFaces[2] ? rec->fFaces[2]->getRefCnt() : 0,
+ rec->fFaces[3] ? rec->fFaces[3]->getRefCnt() : 0);
+ rec = rec->fNext;
+ }
+ } else {
+ SkDebugf("gFamilyHead=%p", gFamilyHead);
+ }
+
+}
+
+
/* Load info from a configuration file that populates the system/fallback font structures
*/
static void load_font_info() {
-// load_font_info_xml("/system/etc/system_fonts.xml");
SkTDArray<FontFamily*> fontFamilies;
getFontFamilies(fontFamilies);
@@ -513,9 +569,9 @@ static void load_font_info() {
*
* gFamilyHeadAndNameListMutex must already be acquired.
*/
-static void load_system_fonts() {
- // check if we've already be called
- if (NULL != gDefaultNormal) {
+static void init_system_fonts() {
+ // check if we've already been called
+ if (gDefaultNormal) {
return;
}
@@ -588,6 +644,65 @@ static void load_system_fonts() {
gFallbackFonts[fallbackCount] = 0;
}
+static size_t find_uniqueID(const char* filename) {
+ // uniqueID is the index, offset by one, of the associated element in gSystemFonts[]
+ // return 0 if not found
+ const FontInitRec* rec = gSystemFonts;
+ for (size_t i = 0; i < gNumSystemFonts; i++) {
+ if (strcmp(rec[i].fFileName, filename) == 0) {
+ return i+1;
+ }
+ }
+ return 0;
+}
+
+static void reload_fallback_fonts() {
+ SkGraphics::PurgeFontCache();
+
+ SkTDArray<FontFamily*> fallbackFamilies;
+ getFallbackFontFamilies(fallbackFamilies);
+
+ for (int i = 0; i < fallbackFamilies.count(); ++i) {
+ FontFamily *family = fallbackFamilies[i];
+
+ for (int j = 0; j < family->fFileNames.count(); ++j) {
+ if (family->fFileNames[j]) {
+ size_t uniqueID = find_uniqueID(family->fFileNames[j]);
+ if (uniqueID != gFallbackFonts[i])
+ gFallbackFonts[i] = uniqueID;
+ break; // The fallback set contains only the first font of each family
+ }
+ }
+ }
+}
+
+static void load_system_fonts() {
+#if !defined(SK_BUILD_FOR_ANDROID_NDK)
+ static char prevLanguage[3];
+ static char prevRegion[3];
+ char language[3] = "";
+ char region[3] = "";
+
+ getLocale(language, region);
+
+ if (!gDefaultNormal) {
+ strncpy(prevLanguage, language, 2);
+ strncpy(prevRegion, region, 2);
+ init_system_fonts();
+ } else if (strncmp(language, prevLanguage, 2) || strncmp(region, prevRegion, 2)) {
+ strncpy(prevLanguage, language, 2);
+ strncpy(prevRegion, region, 2);
+ reload_fallback_fonts();
+ }
+#else
+ if (!gDefaultNormal) {
+ init_system_fonts();
+ reload_fallback_fonts();
+ }
+#endif
+}
+
+
///////////////////////////////////////////////////////////////////////////////
void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
@@ -706,7 +821,7 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
tf = find_best_face(gDefaultFamily, style);
}
- // we ref(), since the symantic is to return a new instance
+ // we ref(), since the semantic is to return a new instance
tf->ref();
return tf;
}
@@ -792,6 +907,7 @@ SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
SkASSERT(origTypeface != 0);
SkASSERT(currTypeface != 0);
+ SkASSERT(gFallbackFonts);
// Our fallback list always stores the id of the plain in each fallback
// family, so we transform currFontID to its plain equivalent.