Merge "Revert "Use Elegant fonts for Webkit, Compact fonts for Textview""
diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h
index ace08d8..25c9ecb 100644
--- a/include/core/SkFontHost.h
+++ b/include/core/SkFontHost.h
@@ -154,15 +154,6 @@
      */
     static SkFontID NextLogicalFont(SkFontID currFontID, SkFontID origFontID);
 
-#ifdef SK_BUILD_FOR_ANDROID
-    /*
-     * This Android-only version of NextLogicalFont allows us to pass in an
-     * entire Rec structure so that a caller can change fallback behavior
-     */
-    static SkFontID NextLogicalFont(const SkScalerContext::Rec& rec);
-#endif
-
-
     ///////////////////////////////////////////////////////////////////////////
 
     /** Given a filled-out rec, the fonthost may decide to modify it to reflect
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 1715013..30ff663 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -665,25 +665,6 @@
         @param locale set the paint's locale value for drawing text.
     */
     void    setTextLocale(const SkString& locale);
-
-
-    enum FontVariant {
-       kDefault_Variant, // Currently setting yourself to Default gives you Compact Variant
-       kCompact_Variant,
-       kElegant_Variant,
-       kLast_Variant = kElegant_Variant,
-    };
-
-    /** Return the font variant
-        @return the font variant used by this paint object
-    */
-    FontVariant getFontVariant() const { return fFontVariant; }
-
-
-    /** Set the font variant
-      @param fontVariant set the paint's font variant for choosing fonts
-    */
-    void setFontVariant(FontVariant fontVariant);
 #endif
 
     /** Return the paint's text size.
@@ -925,7 +906,6 @@
     unsigned        fHinting : 2;
 #ifdef SK_BUILD_FOR_ANDROID
     SkString        fTextLocale;
-    FontVariant     fFontVariant;
 #endif
 
     SkDrawCacheProc    getDrawCacheProc() const;
diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h
index 33c3c3d..9bcf601 100644
--- a/include/core/SkScalerContext.h
+++ b/include/core/SkScalerContext.h
@@ -210,9 +210,6 @@
 #ifdef SK_USE_COLOR_LUMINANCE
         uint32_t    fLumBits;
 #endif
-#ifdef SK_BUILD_FOR_ANDROID
-        SkPaint::FontVariant fFontVariant;
-#endif
         uint8_t     fMaskFormat;
         uint8_t     fStrokeJoin;
         uint16_t    fFlags;
@@ -237,6 +234,7 @@
         SkMask::Format getFormat() const {
             return static_cast<SkMask::Format>(fMaskFormat);
         }
+        
 #ifdef SK_USE_COLOR_LUMINANCE
         SkColor getLuminanceColor() const {
             return fLumBits;
diff --git a/include/ports/SkTypeface_android.h b/include/ports/SkTypeface_android.h
index c3eb3d1..3471a94 100644
--- a/include/ports/SkTypeface_android.h
+++ b/include/ports/SkTypeface_android.h
@@ -10,20 +10,47 @@
 #define SkTypeface_android_DEFINED
 
 #include "SkTypeface.h"
-#include "SkPaint.h"
 
-#include "../harfbuzz/src/harfbuzz-shaper.h"
+enum FallbackScripts {
+    kArabic_FallbackScript,
+    kArmenian_FallbackScript,
+    kBengali_FallbackScript,
+    kDevanagari_FallbackScript,
+    kEthiopic_FallbackScript,
+    kGeorgian_FallbackScript,
+    kHebrewRegular_FallbackScript,
+    kHebrewBold_FallbackScript,
+    kKannada_FallbackScript,
+    kMalayalam_FallbackScript,
+    kTamilRegular_FallbackScript,
+    kTamilBold_FallbackScript,
+    kThai_FallbackScript,
+    kTelugu_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 harfbuzz script id.
- *  @param  style    The font style, for example bold
- *  @param  elegant  true if we want the web friendly elegant version of the font
- *  @return          reference to the matching typeface. Caller must call
- *                   unref() when they are done.
+ *  @param  script  The script id.
+ *  @return reference to the matching typeface. Caller must call
+ *          unref() when they are done.
  */
-SK_API SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style,
-        SkPaint::FontVariant fontVariant = SkPaint::kDefault_Variant);
+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/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 412ab2b..e1932a7 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -72,7 +72,6 @@
     fHinting    = SkPaintDefaults_Hinting;
 #ifdef SK_BUILD_FOR_ANDROID
     new(&fTextLocale) SkString();
-    fFontVariant = kDefault_Variant;
     fGenerationID = 0;
 #endif
 }
@@ -373,18 +372,6 @@
         GEN_ID_INC;
     }
 }
-
-void SkPaint::setFontVariant(FontVariant fontVariant) {
-    if ((unsigned)fontVariant <= kLast_Variant) {
-        GEN_ID_INC_EVAL((unsigned)fontVariant != fFontVariant);
-        fFontVariant = fontVariant;
-    } else {
-#ifdef SK_REPORT_API_RANGE_CHECK
-        SkDebugf("SkPaint::setFontVariant(%d) out of range\n", fontVariant);
-#endif
-    }
-}
-
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1574,9 +1561,6 @@
 #else
     rec->setLuminanceBits(computeLuminance(paint));
 #endif
-#ifdef SK_BUILD_FOR_ANDROID
-    rec->fFontVariant = paint.getFontVariant();
-#endif //SK_BUILD_FOR_ANDROID
 
     /*  Allow the fonthost to modify our rec before we use it as a key into the
         cache. This way if we're asking for something that they will ignore,
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index e33ad7a..2921b1e 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -118,13 +118,7 @@
     // fonthost will determine the next possible font to search, based
     // on the current font in fRec. It will return NULL if ctx is our
     // last font that can be searched (i.e. ultimate fallback font)
-#ifdef SK_BUILD_FOR_ANDROID
-        // On Android, pass entire rec structure so that clients can change fallback behavior
-        uint32_t newFontID = SkFontHost::NextLogicalFont(rec);
-#else
-        uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID);
-#endif
-
+    uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID);
     if (0 == newFontID) {
         return NULL;
     }
diff --git a/src/ports/FontHostConfiguration_android.cpp b/src/ports/FontHostConfiguration_android.cpp
index 9296769..d1164c8 100644
--- a/src/ports/FontHostConfiguration_android.cpp
+++ b/src/ports/FontHostConfiguration_android.cpp
@@ -18,7 +18,6 @@
 #include "FontHostConfiguration_android.h"
 #include "SkString.h"
 #include "SkTDArray.h"
-#include "SkTypeface.h"
 #include <expat.h>
 #if !defined(SK_BUILD_FOR_ANDROID_NDK)
     #include <cutils/properties.h>
@@ -47,13 +46,12 @@
     XML_Parser *parser;                // The expat parser doing the work
     SkTDArray<FontFamily*> &families;  // The array that each family is put into as it is parsed
     FontFamily *currentFamily;         // The current family being created
-    FontFileInfo *currentFontInfo;     // The current fontInfo being created
     int currentTag;                    // A flag to indicate whether we're in nameset/fileset tags
 };
 
 /**
  * Handler for arbitrary text. This is used to parse the text inside each name
- * or file tag. The resulting strings are put into the fNames or FontFileInfo arrays.
+ * or file tag. The resulting strings are put into the fNames or fFileNames arrays.
  */
 void textHandler(void *data, const char *s, int len) {
     FamilyData *familyData = (FamilyData*) data;
@@ -70,9 +68,7 @@
             *(familyData->currentFamily->fNames.append()) = buff;
             break;
         case FILESET_TAG:
-            if (familyData->currentFontInfo) {
-                familyData->currentFontInfo->fFileName = buff;
-            }
+            *(familyData->currentFamily->fFileNames.append()) = buff;
             break;
         default:
             // Noop - don't care about any text that's not in the Fonts or Names list
@@ -82,39 +78,6 @@
 }
 
 /**
- * Handler for font files. This processes the attributes for language and variants
- * then lets textHandler handle the actual file name
- */
-void fontFileElementHandler(FamilyData *familyData, const char **attributes) {
-    FontFileInfo* newFileInfo = new FontFileInfo();
-    if (attributes) {
-        int currentAttributeIndex = 0;
-        while (attributes[currentAttributeIndex]) {
-            const char* attributeName = attributes[currentAttributeIndex];
-            const char* attributeValue = attributes[currentAttributeIndex+1];
-            int nameLength = strlen(attributeName);
-            int valueLength = strlen(attributeValue);
-            if (strncmp(attributeName, "variant", nameLength) == 0) {
-                if (strncmp(attributeValue, "elegant", valueLength) == 0) {
-                    newFileInfo->fVariant = SkPaint::kElegant_Variant;
-                } else if (strncmp(attributeValue, "compact", valueLength) == 0) {
-                    newFileInfo->fVariant = SkPaint::kCompact_Variant;
-                }
-            } else if (strncmp(attributeName, "language", nameLength) == 0) {
-                if (strncmp(attributeValue, "ja", valueLength) == 0) {
-                    newFileInfo->fLanguage = "ja";
-                }  //else if (other languages)
-            }
-            //each element is a pair of attributeName/attributeValue string pairs
-            currentAttributeIndex += 2;
-        }
-    }
-    *(familyData->currentFamily->fFontFileArray.append()) = newFileInfo;
-    familyData->currentFontInfo = newFileInfo;
-    XML_SetCharacterDataHandler(*familyData->parser, textHandler);
-}
-
-/**
  * Handler for the start of a tag. The only tags we expect are family, nameset,
  * fileset, name, and file.
  */
@@ -135,16 +98,14 @@
                 familyData->currentFamily->order = value;
             }
         }
-    } else if (len == 7 && strncmp(tag, "nameset", len) == 0) {
+    } else if (len == 7 && strncmp(tag, "nameset", len)== 0) {
         familyData->currentTag = NAMESET_TAG;
     } else if (len == 7 && strncmp(tag, "fileset", len) == 0) {
         familyData->currentTag = FILESET_TAG;
-    } else if (strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) {
+    } else if ((strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) ||
+            (strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG)) {
         // If it's a Name, parse the text inside
         XML_SetCharacterDataHandler(*familyData->parser, textHandler);
-    } else if (strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG) {
-        // If it's a file, parse the attributes, then parse the text inside
-        fontFileElementHandler(familyData, atts);
     }
 }
 
@@ -159,9 +120,9 @@
         // Done parsing a Family - store the created currentFamily in the families array
         *familyData->families.append() = familyData->currentFamily;
         familyData->currentFamily = NULL;
-    } else if (len == 7 && strncmp(tag, "nameset", len) == 0) {
+    } else if (len == 7 && strncmp(tag, "nameset", len)== 0) {
         familyData->currentTag = NO_TAG;
-    } else if (len == 7 && strncmp(tag, "fileset", len) == 0) {
+    } else if (len == 7 && strncmp(tag, "fileset", len)== 0) {
         familyData->currentTag = NO_TAG;
     } else if ((strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) ||
             (strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG)) {
diff --git a/src/ports/FontHostConfiguration_android.h b/src/ports/FontHostConfiguration_android.h
index c8a70e3..2441f0e 100644
--- a/src/ports/FontHostConfiguration_android.h
+++ b/src/ports/FontHostConfiguration_android.h
@@ -18,27 +18,18 @@
 #define FONTHOSTCONFIGURATION_ANDROID_H_
 
 #include "SkTDArray.h"
-#include "SkPaint.h"
-
-struct FontFileInfo {
-    FontFileInfo() : fVariant(SkPaint::kDefault_Variant), fLanguage(NULL), fFileName(NULL) {}
-    const char*          fFileName;
-    SkPaint::FontVariant fVariant;
-    const char*          fLanguage;  // We may eventually use a enum for this
-};
-
 
 /**
  * The FontFamily data structure is created during parsing and handed back to
  * Skia to fold into its representation of font families. fNames is the list of
- * font names that alias to a font family. fontFileArray is the list of information
- * about each file.  Order is the priority order for the font. This is
+ * font names that alias to a font family. fFileNames is the list of font
+ * filenames for the family. Order is the priority order for the font. This is
  * used internally to determine the order in which to place fallback fonts as
  * they are read from the configuration files.
  */
 struct FontFamily {
-    SkTDArray<const char*>   fNames;
-    SkTDArray<FontFileInfo*> fFontFileArray;
+    SkTDArray<const char*>  fNames;
+    SkTDArray<const char*>  fFileNames;
     int order;
 };
 
diff --git a/src/ports/SkFontHost_android.cpp b/src/ports/SkFontHost_android.cpp
index 0a9cced..afd0ebe 100644
--- a/src/ports/SkFontHost_android.cpp
+++ b/src/ports/SkFontHost_android.cpp
@@ -29,7 +29,7 @@
 #include <string.h>
 #include "SkGlyphCache.h"
 #include "SkTypeface_android.h"
-#include "SkTSearch.h"
+
 
 //#define SkDEBUGF(args       )       SkDebugf args
 
@@ -76,7 +76,7 @@
         SkTypeface::Style style);
 static SkStream* openStreamLocked(uint32_t fontID);
 static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index);
-static SkFontID nextLogicalFontLocked(const SkScalerContext::Rec& rec);
+static SkFontID nextLogicalFontLocked(SkFontID currFontID, SkFontID origFontID);
 static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream);
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -150,12 +150,6 @@
     return NULL;
 }
 
-static SkTypeface* FindBestFace(const FamilyRec* family,
-            SkTypeface::Style style) {
-    SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
-    return findBestFaceLocked(family, style);
-}
-
 static FamilyRec* findFamilyLocked(const SkTypeface* member) {
     FamilyRec* curr = gFamilyHead;
     while (curr != NULL) {
@@ -186,14 +180,6 @@
     return NULL;
 }
 
-/*  Returns the matching typeface, or NULL. If a typeface is found, its refcnt
-    is not modified.
- */
-static SkTypeface* FindFromUniqueID(uint32_t uniqueID) {
-    SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
-    return findFromUniqueIDLocked(uniqueID);
-}
-
 /*  Remove reference to this face from its family. If the resulting family
     is empty (has no faces), return that family, otherwise return NULL
 */
@@ -411,15 +397,8 @@
 
 // used to record our notion of the pre-existing fonts
 struct FontInitRec {
-    const char*          fFileName;
-    const char* const*   fNames;     // null-terminated list
-    SkPaint::FontVariant fVariant;
-};
-
-//used to record information about the fallback fonts
-struct FallbackFontRec {
-    SkFontID             fFontID;
-    SkPaint::FontVariant fVariant;
+    const char*         fFileName;
+    const char* const*  fNames;     // null-terminated list
 };
 
 // deliberately empty, but we use the address to identify fallback fonts
@@ -431,7 +410,7 @@
     null for the list. The names list must be NULL-terminated.
 */
 static SkTDArray<FontInitRec> gSystemFonts;
-static SkTDArray<FallbackFontRec> gFallbackFonts;
+static SkTDArray<SkFontID> gFallbackFonts;
 
 // these globals are assigned (once) by loadSystemFontsLocked()
 static FamilyRec* gDefaultFamily = NULL;
@@ -514,8 +493,8 @@
 
     for (int i = 0; i < fontFamilies.count(); ++i) {
         FontFamily *family = fontFamilies[i];
-        for (int j = 0; j < family->fFontFileArray.count(); ++j) {
-            const char* filename = family->fFontFileArray[j]->fFileName;
+        for (int j = 0; j < family->fFileNames.count(); ++j) {
+            const char* filename = family->fFileNames[j];
             if (haveSystemFont(filename)) {
                 SkDebugf("---- system font and fallback font files specify a duplicate "
                         "font %s, skipping the second occurrence", filename);
@@ -524,7 +503,6 @@
 
             FontInitRec fontInfoRecord;
             fontInfoRecord.fFileName = filename;
-            fontInfoRecord.fVariant = family->fFontFileArray[j]->fVariant;
             if (j == 0) {
                 if (family->fNames.count() == 0) {
                     // Fallback font
@@ -617,10 +595,7 @@
             if (names == gFBNames) {
                 SkDEBUGF(("---- adding %s as fallback[%d] fontID %d\n",
                         gSystemFonts[i].fFileName, gFallbackFonts.count(), tf->uniqueID()));
-                FallbackFontRec newFallbackRec;
-                newFallbackRec.fFontID = tf->uniqueID();
-                newFallbackRec.fVariant = gSystemFonts[i].fVariant;
-                *gFallbackFonts.append() = newFallbackRec;
+                *gFallbackFonts.append() = tf->uniqueID();
             }
 
             firstInFamily = tf;
@@ -659,7 +634,7 @@
 
 static int findFallbackFontIndex(SkFontID fontId) {
     for (int i = 0; i < gFallbackFonts.count(); i++) {
-        if (gFallbackFonts[i].fFontID == fontId) {
+        if (gFallbackFonts[i] == fontId) {
             return i;
         }
     }
@@ -677,8 +652,8 @@
     for (int i = 0; i < fallbackFamilies.count(); ++i) {
         FontFamily *family = fallbackFamilies[i];
 
-        for (int j = 0; j < family->fFontFileArray.count(); ++j) {
-            const char* filename = family->fFontFileArray[j]->fFileName;
+        for (int j = 0; j < family->fFileNames.count(); ++j) {
+            const char* filename = family->fFileNames[j];
             if (filename) {
                 if (!haveSystemFont(filename)) {
                     SkDebugf("---- skipping fallback font %s because it was not "
@@ -705,10 +680,8 @@
 
                 SkDEBUGF(("---- reload %s as fallback[%d] fontID %d\n",
                           filename, gFallbackFonts.count(), uniqueID));
-                FallbackFontRec newFallbackFont;
-                newFallbackFont.fFontID = uniqueID;
-                newFallbackFont.fVariant = family->fFontFileArray[j]->fVariant;
-                *gFallbackFonts.append() = newFallbackFont;
+
+                *gFallbackFonts.append() = uniqueID;
                 break;  // The fallback set contains only the first font of each family
             }
         }
@@ -913,16 +886,16 @@
     }
 }
 
-SkFontID SkFontHost::NextLogicalFont(const SkScalerContext::Rec& rec) {
+SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
     SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
-    return nextLogicalFontLocked(rec);
+    return nextLogicalFontLocked(currFontID, origFontID);
 }
 
-static SkFontID nextLogicalFontLocked(const SkScalerContext::Rec& rec) {
+static SkFontID nextLogicalFontLocked(SkFontID currFontID, SkFontID origFontID) {
     loadSystemFontsLocked();
 
-    const SkTypeface* origTypeface = findFromUniqueIDLocked(rec.fOrigFontID);
-    const SkTypeface* currTypeface = findFromUniqueIDLocked(rec.fFontID);
+    const SkTypeface* origTypeface = findFromUniqueIDLocked(origFontID);
+    const SkTypeface* currTypeface = findFromUniqueIDLocked(currFontID);
 
     SkASSERT(origTypeface != 0);
     SkASSERT(currTypeface != 0);
@@ -938,30 +911,17 @@
      */
     int plainFallbackFontIndex = findFallbackFontIndex(plainFontID);
     int nextFallbackFontIndex = plainFallbackFontIndex + 1;
-
-    // If a rec object is set to prefer "kDefault_Variant" it means they have no preference
-    // In this case, we set the value to "kCompact_Variant"
-    SkPaint::FontVariant recPreference = rec.fFontVariant;
-    if (recPreference == SkPaint::kDefault_Variant) {
-        recPreference = SkPaint::kCompact_Variant;
-    }
-    SkFontID nextFontID = 0;
-    while (nextFallbackFontIndex < gFallbackFonts.count()) {
-        bool normalFont =
-                (gFallbackFonts[nextFallbackFontIndex].fVariant == SkPaint::kDefault_Variant);
-        bool fontChosen = (gFallbackFonts[nextFallbackFontIndex].fVariant == recPreference);
-        if (normalFont || fontChosen) {
-            const SkTypeface* nextTypeface =
-                    findFromUniqueIDLocked(gFallbackFonts[nextFallbackFontIndex].fFontID);
-            nextFontID = findTypefaceLocked(nextTypeface, origTypeface->style())->uniqueID();
-            break;
-        }
-        nextFallbackFontIndex++;
+    SkFontID nextFontID;
+    if (nextFallbackFontIndex == gFallbackFonts.count()) {
+        nextFontID = 0; // no more fallbacks
+    } else {
+        const SkTypeface* nextTypeface = findFromUniqueIDLocked(gFallbackFonts[nextFallbackFontIndex]);
+        nextFontID = findTypefaceLocked(nextTypeface, origTypeface->style())->uniqueID();
     }
 
     SkDEBUGF(("---- nextLogicalFont: currFontID=%d, origFontID=%d, plainFontID=%d, "
             "plainFallbackFontIndex=%d, nextFallbackFontIndex=%d "
-            "=> nextFontID=%d", rec.fFontID, rec.fOrigFontID, plainFontID,
+            "=> nextFontID=%d", currFontID, origFontID, plainFontID,
             plainFallbackFontIndex, nextFallbackFontIndex, nextFontID));
     return nextFontID;
 }
@@ -1006,9 +966,46 @@
 // Function from SkTypeface_android.h
 ///////////////////////////////////////////////////////////////////////////////
 
-static SkFontID findFontIDForChar(SkUnichar uni, SkTypeface::Style style,
-        SkPaint::FontVariant fontVariant) {
-    SkTypeface* face = FindBestFace(gDefaultFamily, style);
+struct FBScriptInfo {
+    const FallbackScripts fScript;
+    const char* fScriptID;
+    const SkTypeface::Style fStyle;
+    const SkUnichar fChar; // representative character for that script type
+    SkFontID fFontID;
+};
+
+#define SK_DEFINE_SCRIPT_ENTRY(script, style, unichar) \
+    { script, #script, style, unichar, 0 }
+
+static FBScriptInfo gFBScriptInfo[] = {
+    SK_DEFINE_SCRIPT_ENTRY(kArabic_FallbackScript,        SkTypeface::kNormal, 0x0600),
+    SK_DEFINE_SCRIPT_ENTRY(kArmenian_FallbackScript,      SkTypeface::kNormal, 0x0531),
+    SK_DEFINE_SCRIPT_ENTRY(kBengali_FallbackScript,       SkTypeface::kNormal, 0x0981),
+    SK_DEFINE_SCRIPT_ENTRY(kDevanagari_FallbackScript,    SkTypeface::kNormal, 0x0901),
+    SK_DEFINE_SCRIPT_ENTRY(kEthiopic_FallbackScript,      SkTypeface::kNormal, 0x1200),
+    SK_DEFINE_SCRIPT_ENTRY(kGeorgian_FallbackScript,      SkTypeface::kNormal, 0x10A0),
+    SK_DEFINE_SCRIPT_ENTRY(kHebrewRegular_FallbackScript, SkTypeface::kNormal, 0x0591),
+    SK_DEFINE_SCRIPT_ENTRY(kHebrewBold_FallbackScript,    SkTypeface::kBold,   0x0591),
+    SK_DEFINE_SCRIPT_ENTRY(kKannada_FallbackScript,       SkTypeface::kNormal, 0x0C90),
+    SK_DEFINE_SCRIPT_ENTRY(kMalayalam_FallbackScript,     SkTypeface::kNormal, 0x0D10),
+    SK_DEFINE_SCRIPT_ENTRY(kTamilRegular_FallbackScript,  SkTypeface::kNormal, 0x0B82),
+    SK_DEFINE_SCRIPT_ENTRY(kTamilBold_FallbackScript,     SkTypeface::kBold,   0x0B82),
+    SK_DEFINE_SCRIPT_ENTRY(kThai_FallbackScript,          SkTypeface::kNormal, 0x0E01),
+    SK_DEFINE_SCRIPT_ENTRY(kTelugu_FallbackScript,        SkTypeface::kNormal, 0x0C10),
+};
+
+static bool gFBScriptInitialized = false;
+static const int gFBScriptInfoCount = sizeof(gFBScriptInfo) / sizeof(FBScriptInfo);
+
+// ensure that if any value is added to the public enum it is also added here
+SK_COMPILE_ASSERT(gFBScriptInfoCount == kFallbackScriptNumber, FBScript_count_mismatch);
+
+
+// this function can't be called if the gFamilyHeadAndNameListMutex is already locked
+static SkFontID findFontIDForChar(SkUnichar uni, SkTypeface::Style style) {
+    gFamilyHeadAndNameListMutex.acquire();
+    SkTypeface* face = findBestFaceLocked(gDefaultFamily, style);
+    gFamilyHeadAndNameListMutex.release();
     if (!face) {
         return 0;
     }
@@ -1016,7 +1013,6 @@
     SkPaint paint;
     paint.setTypeface(face);
     paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
-    paint.setFontVariant(fontVariant);
 
     SkAutoGlyphCache autoCache(paint, NULL);
     SkGlyphCache*    cache = autoCache.getCache();
@@ -1029,93 +1025,71 @@
     return 0;
 }
 
-struct HB_UnicodeMapping {
-    HB_Script script;
-    const SkUnichar unicode;
-};
+// this function can't be called if the gFamilyHeadAndNameListMutex is already locked
+static void initFBScriptInfo() {
+    if (gFBScriptInitialized) {
+        return;
+    }
 
-static HB_UnicodeMapping HB_UnicodeMappingArray[] {
-    {HB_Script_Arabic,        0x0600},
-    {HB_Script_Armenian,      0x0531},
-    {HB_Script_Bengali,       0x0981},
-    {HB_Script_Devanagari,    0x0901},
-    // we don't currently support HB_Script_Ethiopic, it is a placeholder for an upstream merge
-    //{HB_Script_Ethiopic,    0x1200},
-    {HB_Script_Georgian,      0x10A0},
-    {HB_Script_Hebrew,        0x0591},
-    {HB_Script_Kannada,       0x0C90},
-    {HB_Script_Malayalam,     0x0D10},
-    {HB_Script_Tamil,         0x0B82},
-    {HB_Script_Thai,          0x0E01},
-    {HB_Script_Telugu,        0x0C10},
-};
+    // ensure the system fonts are loaded
+    gFamilyHeadAndNameListMutex.acquire();
+    loadSystemFontsLocked();
+    gFamilyHeadAndNameListMutex.release();
 
-// returns 0 for "Not Found"
-static SkUnichar getUnicodeFromHBScript(HB_Script script) {
-    SkUnichar unichar = 0;
-    int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMapping);
-    for (int i = 0; i < numSupportedFonts; i++) {
-        if (script == HB_UnicodeMappingArray[i].script) {
-            unichar = HB_UnicodeMappingArray[i].unicode;
-            break;
+    for (int i = 0; i < gFBScriptInfoCount; i++) {
+        FBScriptInfo& scriptInfo = gFBScriptInfo[i];
+        // selects the best available style for the desired font. However, if
+        // bold is requested and no bold font exists for the typeface containing
+        // the character the next best style is chosen (e.g. normal).
+        scriptInfo.fFontID = findFontIDForChar(scriptInfo.fChar, scriptInfo.fStyle);
+        SkDEBUGF(("gFBScriptInfo[%s] --> %d", scriptInfo.fScriptID, scriptInfo.fFontID));
+    }
+    // mark the value as initialized so we don't repeat our work unnecessarily
+    gFBScriptInitialized = true;
+}
+
+SkTypeface* SkCreateTypefaceForScript(FallbackScripts script) {
+    if (!SkTypeface_ValidScript(script)) {
+        return NULL;
+    }
+
+    // ensure that our table is populated
+    initFBScriptInfo();
+
+    FBScriptInfo& scriptInfo = gFBScriptInfo[script];
+
+    // ensure the element with that index actually maps to the correct script
+    SkASSERT(scriptInfo.fScript == script);
+
+    // if a suitable script could not be found then return NULL
+    if (scriptInfo.fFontID == 0) {
+        return NULL;
+    }
+
+    SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
+
+    // retrieve the typeface the corresponds to this fontID
+    SkTypeface* tf = findFromUniqueIDLocked(scriptInfo.fFontID);
+    // we ref(), since the semantic is to return a new instance
+    tf->ref();
+    return tf;
+}
+
+const char* SkGetFallbackScriptID(FallbackScripts script) {
+    for (int i = 0; i < gFBScriptInfoCount; i++) {
+        if (gFBScriptInfo[i].fScript == script) {
+            return gFBScriptInfo[i].fScriptID;
         }
     }
-    return unichar;
+    return NULL;
 }
 
-struct TypefaceLookupStruct {
-    HB_Script            script;
-    SkTypeface::Style    style;
-    SkPaint::FontVariant fontVariant;
-    SkTypeface*          typeface;
-};
-
-SK_DECLARE_STATIC_MUTEX(gTypefaceTableMutex);  // This is the mutex for gTypefaceTable
-static SkTDArray<TypefaceLookupStruct> gTypefaceTable;  // This is protected by gTypefaceTableMutex
-
-static int typefaceLookupCompare(const TypefaceLookupStruct& first,
-        const TypefaceLookupStruct& second) {
-    if (first.script != second.script) {
-        return (first.script > second.script) ? 1 : -1;
-    }
-    if (first.style != second.style) {
-        return (first.style > second.style) ? 1 : -1;
-    }
-    if (first.fontVariant != second.fontVariant) {
-        return (first.fontVariant > second.fontVariant) ? 1 : -1;
-    }
-    return 0;
-}
-
-SK_API SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style,
-        SkPaint::FontVariant fontVariant) {
-    SkTypeface* retTypeface = NULL;
-
-    SkAutoMutexAcquire ac(gTypefaceTableMutex); // Note: NOT gFamilyHeadAndNameListMutex
-    TypefaceLookupStruct key;
-    key.script = script;
-    key.style = style;
-    key.fontVariant = fontVariant;
-    int index = SkTSearch<TypefaceLookupStruct>(
-            (const TypefaceLookupStruct*) gTypefaceTable.begin(),
-            gTypefaceTable.count(), key, sizeof(TypefaceLookupStruct),
-            &typefaceLookupCompare);
-    if (index >= 0) {
-        retTypeface = gTypefaceTable[index].typeface;
-    }
-    else {
-        SkUnichar unichar = getUnicodeFromHBScript(script);
-        if (!unichar) {
-            return NULL;
+FallbackScripts SkGetFallbackScriptFromID(const char* id) {
+    for (int i = 0; i < gFBScriptInfoCount; i++) {
+        if (strcmp(gFBScriptInfo[i].fScriptID, id) == 0) {
+            return gFBScriptInfo[i].fScript;
         }
-        SkFontID newFontID = findFontIDForChar(unichar, style, fontVariant);
-        // retrieve the typeface that corresponds to this fontID
-        retTypeface = FindFromUniqueID(newFontID);
-        // we ref(), since the semantic is to return a new instance
-        retTypeface->ref();
-        key.typeface = retTypeface;
-        index = ~index;
-        *gTypefaceTable.insert(index) = key;
     }
-    return retTypeface;
+    return kFallbackScriptNumber; // Use kFallbackScriptNumber as an invalid value.
 }
+