Provide better Font fallbacks for DirectX backend
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Nov 2018 05:15:02 +0000 (05:15 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Nov 2018 05:15:02 +0000 (05:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191412
<rdar://problem/45899207>

Reviewed by Zalan Bujtas.

Registration of custom fonts through GDI are not always visible
through the DirectWrite/GDI bridging layer. If a font is not located,
locate the closest matching avialable font rather than failing.

* platform/graphics/FontPlatformData.h:
* platform/graphics/win/FontCustomPlatformData.cpp:
(WebCore::FontCustomPlatformData::fontPlatformData): Use new font
fallback logic.
* platform/graphics/win/FontPlatformDataDirect2D.cpp:
(WebCore::FontPlatformData::platformDataInit):
(WebCore::FontPlatformData::platformIsEqual const):
(WebCore::FontPlatformData::createFallbackFont): Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237980 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/FontPlatformData.h
Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
Source/WebCore/platform/graphics/win/FontPlatformDataDirect2D.cpp
Source/WebCore/platform/graphics/win/ImageBufferDirect2D.cpp

index 92d5215..a47dd0f 100644 (file)
@@ -1,3 +1,24 @@
+2018-11-07  Brent Fulgham  <bfulgham@apple.com>
+
+        Provide better Font fallbacks for DirectX backend
+        https://bugs.webkit.org/show_bug.cgi?id=191412
+        <rdar://problem/45899207>
+
+        Reviewed by Zalan Bujtas.
+
+        Registration of custom fonts through GDI are not always visible
+        through the DirectWrite/GDI bridging layer. If a font is not located,
+        locate the closest matching avialable font rather than failing.
+
+        * platform/graphics/FontPlatformData.h:
+        * platform/graphics/win/FontCustomPlatformData.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData): Use new font
+        fallback logic.
+        * platform/graphics/win/FontPlatformDataDirect2D.cpp:
+        (WebCore::FontPlatformData::platformDataInit):
+        (WebCore::FontPlatformData::platformIsEqual const):
+        (WebCore::FontPlatformData::createFallbackFont): Added.
+
 2018-11-07  Zalan Bujtas  <zalan@apple.com>
 
         Click and touch event listeners on the body don't work
index d18803e..0ecf886 100644 (file)
@@ -150,6 +150,8 @@ public:
 #if USE(DIRECT2D)
     IDWriteFont* dwFont() const { return m_dwFont.get(); }
     IDWriteFontFace* dwFontFace() const { return m_dwFontFace.get(); }
+
+    static HRESULT createFallbackFont(const LOGFONT&, IDWriteFont**);
 #endif
 
     bool isFixedPitch() const;
index 2110670..2facb3f 100644 (file)
@@ -65,7 +65,11 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription&
     logFont.lfUnderline = false;
     logFont.lfStrikeOut = false;
     logFont.lfCharSet = DEFAULT_CHARSET;
+#if USE(CG) || USE(CAIRO)
     logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
+#else
+    logFont.lfOutPrecision = OUT_TT_PRECIS;
+#endif
     logFont.lfQuality = CLEARTYPE_QUALITY;
     logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
     logFont.lfItalic = italic;
@@ -79,6 +83,12 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription&
 #else
     COMPtr<IDWriteFont> dwFont;
     HRESULT hr = Font::systemDWriteGdiInterop()->CreateFontFromLOGFONT(&logFont, &dwFont);
+    if (!SUCCEEDED(hr)) {
+        LOGFONT customFont;
+        hr = ::GetObject(hfont.get(), sizeof(LOGFONT), &customFont);
+        if (SUCCEEDED(hr))
+            hr = FontPlatformData::createFallbackFont(customFont, &dwFont);
+    }
     RELEASE_ASSERT(SUCCEEDED(hr));
     return FontPlatformData(WTFMove(hfont), dwFont.get(), size, bold, italic, renderingMode == FontRenderingMode::Alternate);
 #endif
index e0f424d..8c144ae 100644 (file)
@@ -42,8 +42,11 @@ void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR*
     GetObject(font, sizeof(logfont), &logfont);
 
     HRESULT hr = Font::systemDWriteGdiInterop()->CreateFontFromLOGFONT(&logfont, &m_dwFont);
-    if (!SUCCEEDED(hr))
-        return;
+    if (!SUCCEEDED(hr)) {
+        hr = FontPlatformData::createFallbackFont(logfont, &m_dwFont);
+        if (!SUCCEEDED(hr))
+            return;
+    }
 
     hr = m_dwFont->CreateFontFace(&m_dwFontFace);
     if (!SUCCEEDED(hr))
@@ -116,6 +119,74 @@ bool FontPlatformData::platformIsEqual(const FontPlatformData& other) const
         && fontsAreEqual(m_dwFont.get(), other.m_dwFont.get());
 }
 
+HRESULT FontPlatformData::createFallbackFont(const LOGFONT& logFont, IDWriteFont** dwFont)
+{
+    if (!dwFont)
+        return E_POINTER;
+
+    COMPtr<IDWriteFontCollection> fontCollection;
+    HRESULT hr = Font::systemDWriteFactory()->GetSystemFontCollection(&fontCollection);
+    if (FAILED(hr))
+        return hr;
+
+    wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
+    int localeLength = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH);
+
+    COMPtr<IDWriteFontFamily> fontFamily;
+
+    unsigned fontFamilyCount = fontCollection->GetFontFamilyCount();
+    for (unsigned fontIndex = 0; fontIndex < fontFamilyCount; ++fontIndex) {
+        hr = fontCollection->GetFontFamily(fontIndex, &fontFamily);
+        if (FAILED(hr))
+            return hr;
+
+        COMPtr<IDWriteLocalizedStrings> familyNames;
+        hr = fontFamily->GetFamilyNames(&familyNames);
+        if (FAILED(hr))
+            return hr;
+
+        BOOL exists = false;
+        unsigned localeIndex = 0;
+        if (localeLength)
+            hr = familyNames->FindLocaleName(localeName, &localeIndex, &exists);
+
+        if (SUCCEEDED(hr) && !exists)
+            hr = familyNames->FindLocaleName(L"en-us", &localeIndex, &exists);
+
+        if (FAILED(hr))
+            return hr;
+
+        unsigned familyNameLength = 0;
+        hr = familyNames->GetStringLength(localeIndex, &familyNameLength);
+        if (!SUCCEEDED(hr))
+            return hr;
+
+        Vector<wchar_t> familyName(familyNameLength + 1);
+        hr = familyNames->GetString(localeIndex, familyName.data(), familyName.size());
+        if (!SUCCEEDED(hr))
+            return hr;
+
+        if (!wcscmp(logFont.lfFaceName, familyName.data()))
+            break;
+
+        fontFamily = nullptr;
+    }
+
+    if (!fontFamily) {
+        hr = fontCollection->GetFontFamily(0, &fontFamily);
+        if (FAILED(hr))
+            return hr;
+    }
+
+    DWRITE_FONT_WEIGHT weight = static_cast<DWRITE_FONT_WEIGHT>(logFont.lfWeight);
+    DWRITE_FONT_STRETCH stretch = static_cast<DWRITE_FONT_STRETCH>(logFont.lfQuality);
+    DWRITE_FONT_STYLE style = logFont.lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
+
+    hr = fontFamily->GetFirstMatchingFont(weight, stretch, style, dwFont);
+
+    return hr;
+}
+
 }
 
 #endif
index ea6a17f..1a7a266 100644 (file)
@@ -208,6 +208,10 @@ COMPtr<ID2D1Bitmap> ImageBuffer::copyNativeImage(BackingStoreCopy copyBehavior)
     HRESULT hr = bitmapTarget->GetBitmap(&image);
     ASSERT(SUCCEEDED(hr));
 
+    // FIXME: m_data.data is nullptr even when asking to copy backing store leading to test failures.
+    if (copyBehavior == CopyBackingStore && !m_data.data)
+        copyBehavior = DontCopyBackingStore;
+
     if (!context().isAcceleratedContext()) {
         switch (copyBehavior) {
         case DontCopyBackingStore: