Add CreateFallbackForScript to SkTypeface for Android.
WebKit uses HarfBuzz directly to do Complex Text Layout, so it needs to get the
proper SkTypeface to pass it to HarfBuzz. However, on Android, fallback scripts
have no name, and we can only get them by file name each time (CreateFromFile).
This actually breaks the semantics of SkTypeface, which states 'The ID should
be unique for the underlying font file/data, not unique per typeface instance.'
And add 2 helper function to convert between FallbackScripts enum and font file
name. These are useful for WebKit's FontCache, which needs string as key.
https://codereview.appspot.com/5797066/
git-svn-id: http://skia.googlecode.com/svn/trunk@3403 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/ports/SkTypeface_android.h b/include/ports/SkTypeface_android.h
new file mode 100644
index 0000000..72bb9b6
--- /dev/null
+++ b/include/ports/SkTypeface_android.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTypeface_android_DEFINED
+#define SkTypeface_android_DEFINED
+
+#include "SkTypeface.h"
+
+enum FallbackScripts {
+ kArabic_FallbackScript,
+ kEthiopic_FallbackScript,
+ kHebrewRegular_FallbackScript,
+ kHebrewBold_FallbackScript,
+ kThai_FallbackScript,
+ kArmenian_FallbackScript,
+ kGeorgian_FallbackScript,
+ kDevanagari_FallbackScript,
+ kBengali_FallbackScript,
+ kTamil_FallbackScript,
+ kFallbackScriptNumber
+};
+
+#define SkTypeface_ValidScript(s) (s >= 0 && s < kFallbackScriptNumber)
+
+/**
+ * Return a new typeface for a fallback script. If the script is
+ * not valid, or can not map to a font, returns null.
+ * @param script The script id.
+ * @return reference to the matching typeface. Caller must call
+ * unref() when they are done.
+ */
+SK_API SkTypeface* SkCreateTypefaceForScript(FallbackScripts script);
+
+/**
+ * Return the string representation for the fallback script on Android.
+ * If the script is not valid, returns null.
+ */
+SK_API const char* SkGetFallbackScriptID(FallbackScripts script);
+
+/**
+ * Return the fallback script enum for the ID on Android.
+ * If the ID is not valid, or can not map to a fallback
+ * script, returns kFallbackScriptNumber.
+ */
+SK_API FallbackScripts SkGetFallbackScriptFromID(const char* id);
+
+#endif
diff --git a/src/ports/SkFontHost_android.cpp b/src/ports/SkFontHost_android.cpp
index 1856cff..0ae1e4e 100644
--- a/src/ports/SkFontHost_android.cpp
+++ b/src/ports/SkFontHost_android.cpp
@@ -23,6 +23,7 @@
#include "SkStream.h"
#include "SkThread.h"
#include "SkTSearch.h"
+#include "SkTypeface_android.h"
#include "FontHostConfiguration_android.h"
#include <stdio.h>
@@ -415,6 +416,21 @@
// deliberately empty, but we use the address to identify fallback fonts
static const char* gFBNames[] = { NULL };
+static const struct {
+ const char* fFileName;
+ FallbackScripts fScript;
+} gFBFileNames[] = {
+ { "DroidNaskh-Regular.ttf", kArabic_FallbackScript },
+ { "DroidSansEthiopic-Regular.ttf", kEthiopic_FallbackScript },
+ { "DroidSansHebrew-Regular.ttf", kHebrewRegular_FallbackScript },
+ { "DroidSansHebrew-Bold.ttf", kHebrewBold_FallbackScript },
+ { "DroidSansThai.ttf", kThai_FallbackScript },
+ { "DroidSansArmenian.ttf", kArmenian_FallbackScript },
+ { "DroidSansGeorgian.ttf", kGeorgian_FallbackScript },
+ { "Lohit-Devanagari.ttf", kDevanagari_FallbackScript },
+ { "Lohit-Bengali.ttf", kBengali_FallbackScript },
+ { "Lohit-Tamil.ttf", kTamil_FallbackScript },
+};
/* Fonts are grouped by family, with the first font in a family having the
list of names (even if that list is empty), and the following members having
@@ -430,6 +446,7 @@
static SkTypeface* gDefaultNormal;
static char** gDefaultNames = NULL;
static uint32_t *gFallbackFonts;
+static uint32_t *gFallbackScriptsMap;
/* Load info from a configuration file that populates the system/fallback font structures
*/
@@ -476,6 +493,7 @@
gNumSystemFonts = fontInfo.count();
gSystemFonts = (FontInitRec*) malloc(gNumSystemFonts * sizeof(FontInitRec));
gFallbackFonts = (uint32_t*) malloc((gNumSystemFonts + 1) * sizeof(uint32_t));
+ gFallbackScriptsMap = (uint32_t*) calloc(kFallbackScriptNumber, sizeof(uint32_t));
if (gSystemFonts == NULL) {
// shouldn't get here
gNumSystemFonts = 0;
@@ -534,6 +552,11 @@
// SkDebugf("---- SkTypeface[%d] %s fontID %d\n", i, rec[i].fFileName, tf->uniqueID());
+ FallbackScripts fallbackScript = SkGetScriptFromFileName(rec[i].fFileName);
+ if (SkTypeface_ValidScript(fallbackScript)) {
+ gFallbackScriptsMap[fallbackScript] = tf->uniqueID();
+ }
+
if (rec[i].fNames != NULL) {
// see if this is one of our fallback fonts
if (rec[i].fNames == gFBNames) {
@@ -688,6 +711,43 @@
return tf;
}
+SkTypeface* SkCreateTypefaceForScript(FallbackScripts script) {
+ if (!SkTypeface_ValidScript(script)) {
+ return NULL;
+ }
+
+ SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
+
+ load_system_fonts();
+
+ if (gFallbackScriptsMap[script] == 0) {
+ return NULL;
+ }
+
+ SkTypeface* tf = find_from_uniqueID(gFallbackScriptsMap[script]);
+ // we ref(), since the symantic is to return a new instance
+ tf->ref();
+ return tf;
+}
+
+const char* SkGetFallbackScriptID(FallbackScripts script) {
+ for (int i = 0; i < sizeof(gFBFileNames) / sizeof(gFBFileNames[0]); i++) {
+ if (gFBFileNames[i].fScript == script) {
+ return gFBFileNames[i].fFileName;
+ }
+ }
+ return NULL;
+}
+
+FallbackScripts SkGetFallbackScriptFromID(const char* fileName) {
+ for (int i = 0; i < sizeof(gFBFileNames) / sizeof(gFBFileNames[0]); i++) {
+ if (strcmp(gFBFileNames[i].fFileName, fileName) == 0) {
+ return gFBFileNames[i].fScript;
+ }
+ }
+ return kFallbackScriptNumber; // Use SkTypeface_ValidScript as an invalid value.
+}
+
SkStream* SkFontHost::OpenStream(uint32_t fontID) {
SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);