fix regression in fallback chain where we don't account for the original font style.

This CL also enforces that the language and variant are the same for all fonts
within a given fallback family.

R=reed@google.com

Review URL: https://codereview.chromium.org/23670009

git-svn-id: http://skia.googlecode.com/svn/trunk@11128 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/ports/SkFontConfigInterface_android.cpp b/src/ports/SkFontConfigInterface_android.cpp
index c9dc944..9a38261 100644
--- a/src/ports/SkFontConfigInterface_android.cpp
+++ b/src/ports/SkFontConfigInterface_android.cpp
@@ -55,8 +55,6 @@
     SkRefPtr<SkTypeface> fTypeface;
     SkString fFileName;
     SkTypeface::Style fStyle;
-    SkPaintOptionsAndroid fPaintOptions;
-    bool fIsFallbackFont;
     bool fIsValid;
     FamilyRecID fFamilyRecID;
 };
@@ -68,10 +66,12 @@
 
     static const int FONT_STYLE_COUNT = 4;
     FontRecID fFontRecID[FONT_STYLE_COUNT];
+    bool fIsFallbackFont;
+    SkPaintOptionsAndroid fPaintOptions;
 };
 
 
-typedef SkTDArray<FontRecID> FallbackFontList;
+typedef SkTDArray<FamilyRecID> FallbackFontList;
 
 class SkFontConfigInterfaceAndroid : public SkFontConfigInterface {
 public:
@@ -105,7 +105,7 @@
                                     const SkPaintOptionsAndroid& options);
 
 private:
-    void addFallbackFont(FontRecID fontRecID);
+    void addFallbackFamily(FamilyRecID fontRecID);
     SkTypeface* getTypefaceForFontRec(FontRecID fontRecID);
     FallbackFontList* getCurrentLocaleFallbackFontList();
     FallbackFontList* findFallbackFontList(const SkLanguage& lang, bool isOriginal = true);
@@ -227,8 +227,6 @@
             FontRec& fontRec = fFonts.push_back();
             fontRec.fFileName = filename;
             fontRec.fStyle = SkTypeface::kNormal;
-            fontRec.fPaintOptions = family->fFontFiles[j]->fPaintOptions;
-            fontRec.fIsFallbackFont = family->fIsFallbackFont;
             fontRec.fIsValid = false;
             fontRec.fFamilyRecID = familyRecID;
 
@@ -241,7 +239,7 @@
                 fontRec.fIsValid = find_name_and_attributes(stream.get(), &name,
                                                             &fontRec.fStyle, &isFixedWidth);
             } else {
-                if (!fontRec.fIsFallbackFont) {
+                if (!family->fIsFallbackFont) {
                     SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
                 }
             }
@@ -261,6 +259,18 @@
                 familyRec = &fFontFamilies.push_back();
                 familyRecID = fFontFamilies.count() - 1;
                 fontRec.fFamilyRecID = familyRecID;
+
+                familyRec->fIsFallbackFont = family->fIsFallbackFont;
+                familyRec->fPaintOptions = family->fFontFiles[j]->fPaintOptions;
+
+                // if this is a fallback font then add it to the appropriate fallback chains
+                if (familyRec->fIsFallbackFont) {
+                    addFallbackFamily(familyRecID);
+                }
+            } else if (familyRec->fPaintOptions != family->fFontFiles[j]->fPaintOptions) {
+                SkDebugf("Every font file within a family must have identical"
+                         "language and variant attributes");
+                sk_throw();
             }
 
             // add this font to the current familyRec
@@ -271,21 +281,16 @@
             }
             familyRec->fFontRecID[fontRec.fStyle] = fontRecID;
 
-            // if this is a fallback font then add it to the appropriate fallback chains
-            if (fontRec.fIsFallbackFont) {
-                addFallbackFont(fontRecID);
-            }
-
             // add the fallback file name to the name dictionary.  This is needed
             // by getFallbackFamilyNameForChar() so that fallback families can be
             // requested by the filenames of the fonts they contain.
-            if (family->fIsFallbackFont && familyRec) {
+            if (familyRec && familyRec->fIsFallbackFont) {
                 insert_into_name_dict(fFamilyNameDict, fontRec.fFileName.c_str(), familyRecID);
             }
         }
 
         // add the names that map to this family to the dictionary for easy lookup
-        if (familyRec && !family->fIsFallbackFont) {
+        if (familyRec && !familyRec->fIsFallbackFont) {
             SkTDArray<const char*> names = family->fNames;
             if (names.isEmpty()) {
                 SkDEBUGFAIL("ERROR: non-fallback font with no name");
@@ -314,10 +319,10 @@
     const char* fallbackLang = iter.next(&fallbackList);
     while(fallbackLang != NULL) {
         for (int i = 0; i < fDefaultFallbackList.count(); i++) {
-            FontRecID fontRecID = fDefaultFallbackList[i];
-            const SkString& fontLang = fFonts[fontRecID].fPaintOptions.getLanguage().getTag();
+            FamilyRecID familyRecID = fDefaultFallbackList[i];
+            const SkString& fontLang = fFontFamilies[familyRecID].fPaintOptions.getLanguage().getTag();
             if (strcmp(fallbackLang, fontLang.c_str()) != 0) {
-                fallbackList->push(fontRecID);
+                fallbackList->push(familyRecID);
             }
         }
         // move to the next fallback list in the dictionary
@@ -334,16 +339,16 @@
     }
 }
 
-void SkFontConfigInterfaceAndroid::addFallbackFont(FontRecID fontRecID) {
-    SkASSERT(fontRecID < fFonts.count());
-    const FontRec& fontRec = fFonts[fontRecID];
-    SkASSERT(fontRec.fIsFallbackFont);
+void SkFontConfigInterfaceAndroid::addFallbackFamily(FamilyRecID familyRecID) {
+    SkASSERT(familyRecID < fFontFamilies.count());
+    const FamilyRec& familyRec = fFontFamilies[familyRecID];
+    SkASSERT(familyRec.fIsFallbackFont);
 
     // add to the default fallback list
-    fDefaultFallbackList.push(fontRecID);
+    fDefaultFallbackList.push(familyRecID);
 
     // stop here if it is the default language tag
-    const SkString& languageTag = fontRec.fPaintOptions.getLanguage().getTag();
+    const SkString& languageTag = familyRec.fPaintOptions.getLanguage().getTag();
     if (languageTag.isEmpty()) {
         return;
     }
@@ -356,7 +361,7 @@
         fFallbackFontDict.set(languageTag.c_str(), customList);
     }
     SkASSERT(customList != NULL);
-    customList->push(fontRecID);
+    customList->push(familyRecID);
 }
 
 
@@ -502,7 +507,8 @@
 bool SkFontConfigInterfaceAndroid::getFallbackFamilyNameForChar(SkUnichar uni, SkString* name) {
     FallbackFontList* fallbackFontList = this->getCurrentLocaleFallbackFontList();
     for (int i = 0; i < fallbackFontList->count(); i++) {
-        FontRecID fontRecID = fallbackFontList->getAt(i);
+        FamilyRecID familyRecID = fallbackFontList->getAt(i);
+        FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], SkTypeface::kNormal);
         SkTypeface* face = this->getTypefaceForFontRec(fontRecID);
 
         SkPaint paint;
@@ -593,6 +599,12 @@
     FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguage());
     SkASSERT(currentFallbackList);
 
+    SkTypeface::Style origStyle = SkTypeface::kNormal;
+    const SkTypeface* origTypeface = SkTypefaceCache::FindByID(origFontID);
+    if (NULL != origTypeface) {
+        origStyle = origTypeface->style();
+    }
+
     // we must convert currTypeface into a FontRecID
     FontRecID currFontRecID = INVALID_FONT_REC_ID;
     const SkTypeface* currTypeface = SkTypefaceCache::FindByID(currFontID);
@@ -603,8 +615,13 @@
         SkASSERT(INVALID_FONT_REC_ID != currFontRecID);
     }
 
+    FamilyRecID currFamilyRecID = INVALID_FAMILY_REC_ID;
+    if (INVALID_FONT_REC_ID != currFontRecID) {
+        currFamilyRecID = fFonts[currFontRecID].fFamilyRecID;
+    }
+
     // lookup the index next font in the chain
-    int currFallbackFontIndex = currentFallbackList->find(currFontRecID);
+    int currFallbackFontIndex = currentFallbackList->find(currFamilyRecID);
     // We add 1 to the returned index for 2 reasons: (1) if find succeeds it moves
     // our index to the next entry in the list; (2) if find() fails it returns
     // -1 and incrementing it will set our starting index to 0 (the head of the list)
@@ -625,9 +642,10 @@
 
     SkTypeface* nextLogicalTypeface = 0;
     while (nextFallbackFontIndex < currentFallbackList->count()) {
-        FontRecID fontRecID = currentFallbackList->getAt(nextFallbackFontIndex);
-        if ((fFonts[fontRecID].fPaintOptions.getFontVariant() & acceptedVariants) != 0) {
-            nextLogicalTypeface = this->getTypefaceForFontRec(fontRecID);
+        FamilyRecID familyRecID = currentFallbackList->getAt(nextFallbackFontIndex);
+        if ((fFontFamilies[familyRecID].fPaintOptions.getFontVariant() & acceptedVariants) != 0) {
+            FontRecID matchedFont = find_best_style(fFontFamilies[familyRecID], origStyle);
+            nextLogicalTypeface = this->getTypefaceForFontRec(matchedFont);
             break;
         }
         nextFallbackFontIndex++;