Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / fonts / skia / FontCacheSkia.cpp
index 1dfc9c7..6fcbca2 100644 (file)
 
 #include "config.h"
 
+#if !OS(WIN) && !OS(ANDROID)
+#include "SkFontConfigInterface.h"
+#endif
 #include "SkFontMgr.h"
+#include "SkStream.h"
 #include "SkTypeface.h"
 #include "platform/NotImplemented.h"
 #include "platform/fonts/AlternateFontFamily.h"
 #include "platform/fonts/FontCache.h"
 #include "platform/fonts/FontDescription.h"
+#include "platform/fonts/FontFaceCreationParams.h"
 #include "platform/fonts/SimpleFontData.h"
+#include "public/platform/Platform.h"
+#include "public/platform/linux/WebSandboxSupport.h"
 #include "wtf/Assertions.h"
 #include "wtf/text/AtomicString.h"
 #include "wtf/text/CString.h"
 #include <unicode/locid.h>
 
-namespace WebCore {
+#if !OS(WIN) && !OS(ANDROID)
+static SkStream* streamForFontconfigInterfaceId(int fontconfigInterfaceId)
+{
+    SkAutoTUnref<SkFontConfigInterface> fci(SkFontConfigInterface::RefGlobal());
+    SkFontConfigInterface::FontIdentity fontIdentity;
+    fontIdentity.fID = fontconfigInterfaceId;
+    return fci->openStream(fontIdentity);
+}
+#endif
+
+namespace blink {
 
 void FontCache::platformInit()
 {
 }
 
+PassRefPtr<SimpleFontData> FontCache::fallbackOnStandardFontStyle(
+    const FontDescription& fontDescription, UChar32 character)
+{
+    FontDescription substituteDescription(fontDescription);
+    substituteDescription.setStyle(FontStyleNormal);
+    substituteDescription.setWeight(FontWeightNormal);
+
+    FontFaceCreationParams creationParams(substituteDescription.family().family());
+    FontPlatformData* substitutePlatformData = getFontPlatformData(substituteDescription, creationParams);
+    if (substitutePlatformData && substitutePlatformData->fontContainsCharacter(character)) {
+        FontPlatformData platformData = FontPlatformData(*substitutePlatformData);
+        platformData.setSyntheticBold(fontDescription.weight() >= FontWeight600);
+        platformData.setSyntheticItalic(fontDescription.style() == FontStyleItalic);
+        return fontDataFromFontPlatformData(&platformData, DoNotRetain);
+    }
+
+    return nullptr;
+}
+
 #if !OS(WIN) && !OS(ANDROID)
 PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescription& fontDescription, UChar32 c, const SimpleFontData*)
 {
-    icu::Locale locale = icu::Locale::getDefault();
+    // First try the specified font with standard style & weight.
+    if (fontDescription.style() == FontStyleItalic
+        || fontDescription.weight() >= FontWeight600) {
+        RefPtr<SimpleFontData> fontData = fallbackOnStandardFontStyle(
+            fontDescription, c);
+        if (fontData)
+            return fontData;
+    }
+
     FontCache::PlatformFallbackFont fallbackFont;
-    FontCache::getFontForCharacter(c, locale.getLanguage(), &fallbackFont);
+    FontCache::getFontForCharacter(c, "", &fallbackFont);
     if (fallbackFont.name.isEmpty())
         return nullptr;
 
-    AtomicString atomicFamily(fallbackFont.name);
+    FontFaceCreationParams creationParams;
+    creationParams = FontFaceCreationParams(fallbackFont.filename, fallbackFont.fontconfigInterfaceId, fallbackFont.ttcIndex);
+
     // Changes weight and/or italic of given FontDescription depends on
     // the result of fontconfig so that keeping the correct font mapping
     // of the given character. See http://crbug.com/32109 for details.
@@ -77,7 +123,7 @@ PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescrip
         description.setStyle(FontStyleNormal);
     }
 
-    FontPlatformData* substitutePlatformData = getFontPlatformData(description, atomicFamily);
+    FontPlatformData* substitutePlatformData = getFontPlatformData(description, creationParams);
     if (!substitutePlatformData)
         return nullptr;
     FontPlatformData platformData = FontPlatformData(*substitutePlatformData);
@@ -90,27 +136,27 @@ PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescrip
 
 PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain)
 {
-    const AtomicString fallbackFontFamily = getFallbackFontFamily(description);
-    const FontPlatformData* fontPlatformData = getFontPlatformData(description, fallbackFontFamily);
+    const FontFaceCreationParams fallbackCreationParams(getFallbackFontFamily(description));
+    const FontPlatformData* fontPlatformData = getFontPlatformData(description, fallbackCreationParams);
 
     // We should at least have Sans or Arial which is the last resort fallback of SkFontHost ports.
     if (!fontPlatformData) {
-        DEFINE_STATIC_LOCAL(const AtomicString, sansStr, ("Sans", AtomicString::ConstructFromLiteral));
-        fontPlatformData = getFontPlatformData(description, sansStr);
+        DEFINE_STATIC_LOCAL(const FontFaceCreationParams, sansCreationParams, (AtomicString("Sans", AtomicString::ConstructFromLiteral)));
+        fontPlatformData = getFontPlatformData(description, sansCreationParams);
     }
     if (!fontPlatformData) {
-        DEFINE_STATIC_LOCAL(const AtomicString, arialStr, ("Arial", AtomicString::ConstructFromLiteral));
-        fontPlatformData = getFontPlatformData(description, arialStr);
+        DEFINE_STATIC_LOCAL(const FontFaceCreationParams, arialCreationParams, (AtomicString("Arial", AtomicString::ConstructFromLiteral)));
+        fontPlatformData = getFontPlatformData(description, arialCreationParams);
     }
 #if OS(WIN)
     // Try some more Windows-specific fallbacks.
     if (!fontPlatformData) {
-        DEFINE_STATIC_LOCAL(const AtomicString, msuigothicStr, ("MS UI Gothic", AtomicString::ConstructFromLiteral));
-        fontPlatformData = getFontPlatformData(description, msuigothicStr);
+        DEFINE_STATIC_LOCAL(const FontFaceCreationParams, msuigothicCreationParams, (AtomicString("MS UI Gothic", AtomicString::ConstructFromLiteral)));
+        fontPlatformData = getFontPlatformData(description, msuigothicCreationParams);
     }
     if (!fontPlatformData) {
-        DEFINE_STATIC_LOCAL(const AtomicString, mssansserifStr, ("Microsoft Sans Serif", AtomicString::ConstructFromLiteral));
-        fontPlatformData = getFontPlatformData(description, mssansserifStr);
+        DEFINE_STATIC_LOCAL(const FontFaceCreationParams, mssansserifCreationParams, (AtomicString("Microsoft Sans Serif", AtomicString::ConstructFromLiteral)));
+        fontPlatformData = getFontPlatformData(description, mssansserifCreationParams);
     }
 #endif
 
@@ -118,8 +164,45 @@ PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescri
     return fontDataFromFontPlatformData(fontPlatformData, shouldRetain);
 }
 
-PassRefPtr<SkTypeface> FontCache::createTypeface(const FontDescription& fontDescription, const AtomicString& family, CString& name)
+#if OS(WIN)
+static inline SkFontStyle fontStyle(const FontDescription& fontDescription)
+{
+    int width = static_cast<int>(fontDescription.stretch());
+    int weight = (fontDescription.weight() - FontWeight100 + 1) * 100;
+    SkFontStyle::Slant slant = fontDescription.style() == FontStyleItalic
+        ? SkFontStyle::kItalic_Slant
+        : SkFontStyle::kUpright_Slant;
+    return SkFontStyle(weight, width, slant);
+}
+
+COMPILE_ASSERT(FontStretchUltraCondensed == SkFontStyle::kUltraCondensed_Width,
+    FontStretchUltraCondensedMapsTokUltraCondensed_Width);
+COMPILE_ASSERT(FontStretchNormal == SkFontStyle::kNormal_Width,
+    FontStretchNormalMapsTokNormal_Width);
+COMPILE_ASSERT(FontStretchUltraExpanded == SkFontStyle::kUltaExpanded_Width,
+    FontStretchUltraExpandedMapsTokUltaExpanded_Width);
+#endif
+
+PassRefPtr<SkTypeface> FontCache::createTypeface(const FontDescription& fontDescription, const FontFaceCreationParams& creationParams, CString& name)
 {
+#if !OS(WIN) && !OS(ANDROID)
+    if (creationParams.creationType() == CreateFontByFciIdAndTtcIndex) {
+        // TODO(dro): crbug.com/381620 Use creationParams.ttcIndex() after
+        // https://code.google.com/p/skia/issues/detail?id=1186 gets fixed.
+        SkTypeface* typeface = nullptr;
+        if (Platform::current()->sandboxSupport())
+            typeface = SkTypeface::CreateFromStream(streamForFontconfigInterfaceId(creationParams.fontconfigInterfaceId()));
+        else
+            typeface = SkTypeface::CreateFromFile(creationParams.filename().data());
+
+        if (typeface)
+            return adoptRef(typeface);
+        else
+            return nullptr;
+    }
+#endif
+
+    AtomicString family = creationParams.family();
     // 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-")) {
@@ -130,38 +213,44 @@ PassRefPtr<SkTypeface> FontCache::createTypeface(const FontDescription& fontDesc
     }
 
     int style = SkTypeface::kNormal;
-    if (fontDescription.weight() >= FontWeightBold)
+    if (fontDescription.weight() >= FontWeight600)
         style |= SkTypeface::kBold;
     if (fontDescription.style())
         style |= SkTypeface::kItalic;
 
 #if OS(WIN)
     if (s_sideloadedFonts) {
-        HashMap<String, SkTypeface*>::iterator sideloadedFont = s_sideloadedFonts->find(name.data());
-        if (sideloadedFont != s_sideloadedFonts->end()) {
+        HashMap<String, SkTypeface*>::iterator sideloadedFont =
+            s_sideloadedFonts->find(name.data());
+        if (sideloadedFont != s_sideloadedFonts->end())
             return adoptRef(sideloadedFont->value);
-        }
     }
-    // FIXME: Use SkFontStyle and matchFamilyStyle instead of legacyCreateTypeface.
-    if (m_fontManager)
-        return adoptRef(m_fontManager->legacyCreateTypeface(name.data(), style));
+
+    if (m_fontManager) {
+        return adoptRef(useDirectWrite()
+            ? m_fontManager->matchFamilyStyle(name.data(), fontStyle(fontDescription))
+            : m_fontManager->legacyCreateTypeface(name.data(), style)
+            );
+    }
 #endif
 
+    // FIXME: Use m_fontManager, SkFontStyle and matchFamilyStyle instead of
+    // CreateFromName on all platforms.
     return adoptRef(SkTypeface::CreateFromName(name.data(), static_cast<SkTypeface::Style>(style)));
 }
 
 #if !OS(WIN)
-FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family, float fontSize)
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const FontFaceCreationParams& creationParams, float fontSize)
 {
     CString name;
-    RefPtr<SkTypeface> tf(createTypeface(fontDescription, family, name));
+    RefPtr<SkTypeface> tf(createTypeface(fontDescription, creationParams, name));
     if (!tf)
         return 0;
 
     FontPlatformData* result = new FontPlatformData(tf,
         name.data(),
         fontSize,
-        (fontDescription.weight() >= FontWeightBold && !tf->isBold()) || fontDescription.isSyntheticBold(),
+        (fontDescription.weight() >= FontWeight600 && !tf->isBold()) || fontDescription.isSyntheticBold(),
         (fontDescription.style() && !tf->isItalic()) || fontDescription.isSyntheticItalic(),
         fontDescription.orientation(),
         fontDescription.useSubpixelPositioning());
@@ -169,4 +258,4 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
 }
 #endif // !OS(WIN)
 
-} // namespace WebCore
+} // namespace blink