Cherry pick: Try last resort on no-match in platformFallbackForCharacter on Android

Bug:13237403

Original description:
Try last resort on no-match in platformFallbackForCharacter on Android

On Android, some locale-preferred fonts (e.g. DroidSansFallback.ttf for
Chinese locale) doesn't contain all characters that the default locale
system fonts contain.

For characters that is missing in the font, fallback to the default
locale system font, by calling getLastResortFallbackFont() in
FontCache::platformFallbackForCharacter().

Also modified getLastResortFallbackFont() to prefer Skia default font
instead of the hard-coded default font (sans) and to map also cursive
and fantasy generic families.

Combined similar code in FontCacheSkia.cpp.

BUG=347121
TEST=FontCacheAndroid.platformFallbackForCharacter (will be enabled in
another CL)
R=dglazkov@chromium.org

Committed:
https://src.chromium.org/viewvc/blink?view=rev&revision=168410

Change-Id: I5262e759d7221b191d794df2c30099f877ecfdef
diff --git a/Source/platform/fonts/AlternateFontFamily.h b/Source/platform/fonts/AlternateFontFamily.h
index f2648d2..c88d237 100644
--- a/Source/platform/fonts/AlternateFontFamily.h
+++ b/Source/platform/fonts/AlternateFontFamily.h
@@ -107,18 +107,26 @@
 
 inline const AtomicString getFallbackFontFamily(const FontDescription& description)
 {
-    DEFINE_STATIC_LOCAL(const AtomicString, sansStr, ("Sans", AtomicString::ConstructFromLiteral));
-    DEFINE_STATIC_LOCAL(const AtomicString, serifStr, ("Serif", AtomicString::ConstructFromLiteral));
-    DEFINE_STATIC_LOCAL(const AtomicString, monospaceStr, ("Monospace", AtomicString::ConstructFromLiteral));
+    DEFINE_STATIC_LOCAL(const AtomicString, sansStr, ("sans-serif", AtomicString::ConstructFromLiteral));
+    DEFINE_STATIC_LOCAL(const AtomicString, serifStr, ("serif", AtomicString::ConstructFromLiteral));
+    DEFINE_STATIC_LOCAL(const AtomicString, monospaceStr, ("monospace", AtomicString::ConstructFromLiteral));
+    DEFINE_STATIC_LOCAL(const AtomicString, cursiveStr, ("cursive", AtomicString::ConstructFromLiteral));
+    DEFINE_STATIC_LOCAL(const AtomicString, fantasyStr, ("fantasy", AtomicString::ConstructFromLiteral));
 
     switch (description.genericFamily()) {
+    case FontDescription::SansSerifFamily:
+        return sansStr;
     case FontDescription::SerifFamily:
         return serifStr;
     case FontDescription::MonospaceFamily:
         return monospaceStr;
-    case FontDescription::SansSerifFamily:
+    case FontDescription::CursiveFamily:
+        return cursiveStr;
+    case FontDescription::FantasyFamily:
+        return fantasyStr;
     default:
-        return sansStr;
+        // Let the caller use the system default font.
+        return emptyAtom;
     }
 }
 
diff --git a/Source/platform/fonts/android/FontCacheAndroid.cpp b/Source/platform/fonts/android/FontCacheAndroid.cpp
index 58ca789..b998878 100644
--- a/Source/platform/fonts/android/FontCacheAndroid.cpp
+++ b/Source/platform/fonts/android/FontCacheAndroid.cpp
@@ -64,7 +64,8 @@
 
     SkString skiaFamilyName;
     if (!SkGetFallbackFamilyNameForChar(c, locale, &skiaFamilyName) || skiaFamilyName.isEmpty())
-        return AtomicString();
+        return emptyAtom;
+
     return skiaFamilyName.c_str();
 }
 
@@ -72,7 +73,7 @@
 {
     AtomicString familyName = getFamilyNameForCharacter(c, fontDescription.script());
     if (familyName.isEmpty())
-        return 0;
+        return getLastResortFallbackFont(fontDescription, DoNotRetain);
     return fontDataFromFontPlatformData(getFontPlatformData(fontDescription, familyName), DoNotRetain);
 }
 
diff --git a/Source/platform/fonts/android/FontCacheAndroidTest.cpp b/Source/platform/fonts/android/FontCacheAndroidTest.cpp
new file mode 100644
index 0000000..2a2f369
--- /dev/null
+++ b/Source/platform/fonts/android/FontCacheAndroidTest.cpp
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "platform/fonts/FontCache.h"
+
+#include "platform/fonts/SimpleFontData.h"
+#include <gtest/gtest.h>
+
+namespace WebCore {
+
+TEST(FontCacheAndroid, platformFallbackForCharacter)
+{
+    // A Latin character in the common locale system font, but not in the
+    // Chinese locale-preferred font.
+    const UChar32 testChar = 228;
+
+    FontDescription fontDescription;
+    fontDescription.setScript(USCRIPT_SIMPLIFIED_HAN);
+    fontDescription.setGenericFamily(FontDescription::StandardFamily);
+
+    FontCache* fontCache = FontCache::fontCache();
+    ASSERT_TRUE(fontCache);
+    RefPtr<SimpleFontData> fontData = fontCache->platformFallbackForCharacter(fontDescription, testChar, 0);
+    EXPECT_TRUE(fontData);
+}
+
+} // namespace WebCore
diff --git a/Source/platform/fonts/skia/FontCacheSkia.cpp b/Source/platform/fonts/skia/FontCacheSkia.cpp
index 6498da1..55e0433 100644
--- a/Source/platform/fonts/skia/FontCacheSkia.cpp
+++ b/Source/platform/fonts/skia/FontCacheSkia.cpp
@@ -86,7 +86,7 @@
     return fontDataFromFontPlatformData(&platformData, DoNotRetain);
 }
 
-#endif // !OS(WINDOWNS) && !OS(ANDROID)
+#endif // !OS(WIN) && !OS(ANDROID)
 
 PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain)
 {
@@ -107,29 +107,10 @@
 
 PassRefPtr<SkTypeface> FontCache::createTypeface(const FontDescription& fontDescription, const AtomicString& family, CString& name)
 {
-    name = "";
-
     // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into
     // the fallback name (like "monospace") that fontconfig understands.
     if (!family.length() || family.startsWith("-webkit-")) {
-        static const struct {
-            FontDescription::GenericFamilyType mType;
-            const char* mName;
-        } fontDescriptions[] = {
-            { FontDescription::SerifFamily, "serif" },
-            { FontDescription::SansSerifFamily, "sans-serif" },
-            { FontDescription::MonospaceFamily, "monospace" },
-            { FontDescription::CursiveFamily, "cursive" },
-            { FontDescription::FantasyFamily, "fantasy" }
-        };
-
-        FontDescription::GenericFamilyType type = fontDescription.genericFamily();
-        for (unsigned i = 0; i < SK_ARRAY_COUNT(fontDescriptions); i++) {
-            if (type == fontDescriptions[i].mType) {
-                name = fontDescriptions[i].mName;
-                break;
-            }
-        }
+        name = getFallbackFontFamily(fontDescription).string().utf8();
     } else {
         // convert the name to utf8
         name = family.string().utf8();
@@ -167,6 +148,6 @@
         fontDescription.useSubpixelPositioning());
     return result;
 }
-#endif // !OS(WINDOWNS)
+#endif // !OS(WIN)
 
 } // namespace WebCore