[FTW] Support web fonts
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Aug 2019 21:49:01 +0000 (21:49 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Aug 2019 21:49:01 +0000 (21:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=200771
<rdar://problem/54350291>

Reviewed by Dean Jackson.

The current code path for handling web fonts uses 'AddFontMemResourceEx'. Unfortunately, this only updates the font caches used by GDI, and is not exposed to DirectWrite.

This patch does the following:
1. Moves some code into a new DirectWriteUtilities file, similar to how Direct2D is handled, so we
   can share code in more places.
2. After adding the font to GDI, it adds the font information to the DirectWrite font cache.
3. Add logic to check the overall system DirectWrite fonts, as well as the custom font cache used
   for downloaded fonts.

* PlatformFTW.cmake: Add DirectWriteUtilities.cpp
* css/CSSFontFaceSource.cpp:
* loader/cache/CachedFont.cpp:
* loader/cache/CachedSVGFont.cpp:
* platform/graphics/Font.cpp:
* platform/graphics/Font.h:
* platform/graphics/FontCache.cpp:
* platform/graphics/FontPlatformData.cpp:
* platform/graphics/FontPlatformData.h:
* platform/graphics/opentype/OpenTypeUtilities.cpp:
(WebCore::renameAndActivateFont):
* platform/graphics/win/DirectWriteUtilities.cpp: Added.
* platform/graphics/win/DirectWriteUtilities.h: Added.
* platform/graphics/win/FontCacheWin.cpp:
(WebCore::createGDIFont):
* platform/graphics/win/FontCascadeDirect2D.cpp:
* platform/graphics/win/FontCustomPlatformData.cpp:
(WebCore::FontCustomPlatformData::fontPlatformData):
* platform/graphics/win/FontPlatformDataDirect2D.cpp:
(WebCore::FontPlatformData::platformDataInit):
(WebCore::FontPlatformData::FontPlatformData):
(WebCore::FontPlatformData::createFallbackFont):
* platform/graphics/win/FontPlatformDataWin.cpp:
* platform/graphics/win/GlyphPageTreeNodeDirect2D.cpp:
(WebCore::GlyphPage::fill):
* platform/graphics/win/GraphicsContextDirect2D.cpp:
* platform/graphics/win/SimpleFontDataDirect2D.cpp:
(WebCore::Font::systemDWriteFactory): Deleted.
(WebCore::Font::systemDWriteGdiInterop): Deleted.
* platform/graphics/win/SimpleFontDataWin.cpp:

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

23 files changed:
Source/WebCore/ChangeLog
Source/WebCore/PlatformFTW.cmake
Source/WebCore/css/CSSFontFaceSource.cpp
Source/WebCore/loader/cache/CachedFont.cpp
Source/WebCore/loader/cache/CachedSVGFont.cpp
Source/WebCore/platform/graphics/Font.cpp
Source/WebCore/platform/graphics/Font.h
Source/WebCore/platform/graphics/FontCache.cpp
Source/WebCore/platform/graphics/FontPlatformData.cpp
Source/WebCore/platform/graphics/FontPlatformData.h
Source/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
Source/WebCore/platform/graphics/win/BackingStoreBackendDirect2DImpl.h
Source/WebCore/platform/graphics/win/DirectWriteUtilities.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/win/DirectWriteUtilities.h [new file with mode: 0644]
Source/WebCore/platform/graphics/win/FontCacheWin.cpp
Source/WebCore/platform/graphics/win/FontCascadeDirect2D.cpp
Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
Source/WebCore/platform/graphics/win/FontPlatformDataDirect2D.cpp
Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
Source/WebCore/platform/graphics/win/GlyphPageTreeNodeDirect2D.cpp
Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp
Source/WebCore/platform/graphics/win/SimpleFontDataDirect2D.cpp
Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp

index 44de280..d342388 100644 (file)
@@ -1,3 +1,51 @@
+2019-08-15  Brent Fulgham  <bfulgham@apple.com>
+
+        [FTW] Support web fonts
+        https://bugs.webkit.org/show_bug.cgi?id=200771
+        <rdar://problem/54350291>
+
+        Reviewed by Dean Jackson.
+
+        The current code path for handling web fonts uses 'AddFontMemResourceEx'. Unfortunately, this only updates the font caches used by GDI, and is not exposed to DirectWrite.
+
+        This patch does the following:
+        1. Moves some code into a new DirectWriteUtilities file, similar to how Direct2D is handled, so we
+           can share code in more places.
+        2. After adding the font to GDI, it adds the font information to the DirectWrite font cache.
+        3. Add logic to check the overall system DirectWrite fonts, as well as the custom font cache used
+           for downloaded fonts.
+
+        * PlatformFTW.cmake: Add DirectWriteUtilities.cpp
+        * css/CSSFontFaceSource.cpp:
+        * loader/cache/CachedFont.cpp:
+        * loader/cache/CachedSVGFont.cpp:
+        * platform/graphics/Font.cpp:
+        * platform/graphics/Font.h:
+        * platform/graphics/FontCache.cpp:
+        * platform/graphics/FontPlatformData.cpp:
+        * platform/graphics/FontPlatformData.h:
+        * platform/graphics/opentype/OpenTypeUtilities.cpp:
+        (WebCore::renameAndActivateFont):
+        * platform/graphics/win/DirectWriteUtilities.cpp: Added.
+        * platform/graphics/win/DirectWriteUtilities.h: Added.
+        * platform/graphics/win/FontCacheWin.cpp:
+        (WebCore::createGDIFont):
+        * platform/graphics/win/FontCascadeDirect2D.cpp:
+        * platform/graphics/win/FontCustomPlatformData.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        * platform/graphics/win/FontPlatformDataDirect2D.cpp:
+        (WebCore::FontPlatformData::platformDataInit):
+        (WebCore::FontPlatformData::FontPlatformData):
+        (WebCore::FontPlatformData::createFallbackFont):
+        * platform/graphics/win/FontPlatformDataWin.cpp:
+        * platform/graphics/win/GlyphPageTreeNodeDirect2D.cpp:
+        (WebCore::GlyphPage::fill):
+        * platform/graphics/win/GraphicsContextDirect2D.cpp:
+        * platform/graphics/win/SimpleFontDataDirect2D.cpp:
+        (WebCore::Font::systemDWriteFactory): Deleted.
+        (WebCore::Font::systemDWriteGdiInterop): Deleted.
+        * platform/graphics/win/SimpleFontDataWin.cpp:
+
 2019-08-15  Jer Noble  <jer.noble@apple.com>
 
         [Cocoa] Adopt -preventDisplaySleepForVideoPlayback
index fb051a7..6c3f8c1 100644 (file)
@@ -64,6 +64,7 @@ list(APPEND WebCore_SOURCES
     platform/graphics/win/DIBPixelData.cpp
     platform/graphics/win/Direct2DOperations.cpp
     platform/graphics/win/Direct2DUtilities.cpp
+    platform/graphics/win/DirectWriteUtilities.cpp
     platform/graphics/win/FloatPointDirect2D.cpp
     platform/graphics/win/FloatRectDirect2D.cpp
     platform/graphics/win/FloatSizeDirect2D.cpp
@@ -150,6 +151,41 @@ list(APPEND WebCore_SOURCES
     rendering/RenderThemeWin.cpp
 )
 
+if (USE_CF)
+    list(APPEND WebCore_PRIVATE_INCLUDE_DIRECTORIES
+        "${WEBCORE_DIR}/loader/archive/cf"
+        "${WEBCORE_DIR}/platform/cf"
+        "${WEBCORE_DIR}/platform/cf/win"
+    )
+
+    list(APPEND WebCore_SOURCES
+        editing/SmartReplaceCF.cpp
+
+        loader/archive/cf/LegacyWebArchive.cpp
+
+        platform/cf/KeyedDecoderCF.cpp
+        platform/cf/KeyedEncoderCF.cpp
+        platform/cf/SharedBufferCF.cpp
+
+        platform/cf/win/CertificateCFWin.cpp
+
+        platform/text/cf/HyphenationCF.cpp
+    )
+
+    list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS
+        loader/archive/cf/LegacyWebArchive.h
+
+        platform/cf/win/CertificateCFWin.h
+    )
+
+    list(APPEND WebCore_LIBRARIES ${COREFOUNDATION_LIBRARY})
+    list(APPEND WebCoreTestSupport_LIBRARIES ${COREFOUNDATION_LIBRARY})
+else ()
+    list(APPEND WebCore_SOURCES
+        platform/text/Hyphenation.cpp
+    )
+endif ()
+
 list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS
     accessibility/win/AccessibilityObjectWrapperWin.h
 
@@ -160,6 +196,7 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS
     platform/graphics/win/DIBPixelData.h
     platform/graphics/win/Direct2DOperations.h
     platform/graphics/win/Direct2DUtilities.h
+    platform/graphics/win/DirectWriteUtilities.h
     platform/graphics/win/FullScreenController.h
     platform/graphics/win/FullScreenControllerClient.h
     platform/graphics/win/GraphicsContextImplDirect2D.h
@@ -213,6 +250,13 @@ list(APPEND WebCoreTestSupport_LIBRARIES
     shlwapi
 )
 
+make_directory(${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/WebKit.resources/en.lproj)
+file(COPY
+    "${WEBCORE_DIR}/en.lproj/Localizable.strings"
+    "${WEBCORE_DIR}/en.lproj/mediaControlsLocalizedStrings.js"
+    DESTINATION
+    ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/WebKit.resources/en.lproj
+)
 file(COPY
     "${WEBCORE_DIR}/Modules/mediacontrols/mediaControlsApple.css"
     "${WEBCORE_DIR}/Modules/mediacontrols/mediaControlsApple.js"
index 00fd160..6747a23 100644 (file)
 #include "SVGURIReference.h"
 #endif
 
-#if USE(DIRECT2D)
-#include <dwrite.h>
-#endif
-
 namespace WebCore {
 
 inline void CSSFontFaceSource::setStatus(Status newStatus)
index 693dda0..0851508 100644 (file)
 #include "WOFFFileFormat.h"
 #include <wtf/Vector.h>
 
-#if USE(DIRECT2D)
-#include <dwrite.h>
-#endif
-
 namespace WebCore {
 
 CachedFont::CachedFont(CachedResourceRequest&& request, const PAL::SessionID& sessionID, const CookieJar* cookieJar, Type type)
index bae8db8..0e934f2 100644 (file)
 #include "TypedElementDescendantIterator.h"
 #include "SVGToOTFFontConversion.h"
 
-#if USE(DIRECT2D)
-#include <dwrite.h>
-#endif
-
 namespace WebCore {
 
 CachedSVGFont::CachedSVGFont(CachedResourceRequest&& request, const PAL::SessionID& sessionID, const CookieJar* cookieJar)
index 184b44b..c441e55 100644 (file)
 #include "OpenTypeVerticalData.h"
 #endif
 
-#if USE(DIRECT2D)
-#include <dwrite.h>
-#endif
-
 namespace WebCore {
 
 unsigned GlyphPage::s_count = 0;
index 2e58bd6..5527e74 100644 (file)
@@ -51,7 +51,7 @@
 #endif
 
 #if USE(DIRECT2D)
-interface IDWriteFactory;
+interface IDWriteFactory5;
 interface IDWriteGdiInterop;
 #endif
 
@@ -219,11 +219,6 @@ public:
     static float ascentConsideringMacAscentHack(const WCHAR*, float ascent, float descent);
 #endif
 
-#if USE(DIRECT2D)
-    WEBCORE_EXPORT static IDWriteFactory* systemDWriteFactory();
-    WEBCORE_EXPORT static IDWriteGdiInterop* systemDWriteGdiInterop();
-#endif
-
 private:
     Font(const FontPlatformData&, Origin, Interstitial, Visibility, OrientationFallback);
 
index 0a62a27..07a1087 100644 (file)
 #include "OpenTypeVerticalData.h"
 #endif
 
-#if USE(DIRECT2D)
-#include <dwrite.h>
-#endif
-
 #if PLATFORM(IOS_FAMILY)
 #include <wtf/Lock.h>
 #include <wtf/RecursiveLockAdapter.h>
index 0e3f7a7..9d287af 100644 (file)
 #include <CoreGraphics/CGFont.h>
 #endif
 
-#if USE(DIRECT2D)
-#include <dwrite.h>
-#endif
-
 namespace WebCore {
 
 FontPlatformData::FontPlatformData(WTF::HashTableDeletedValueType)
index 0f03cff..65e471f 100644 (file)
@@ -65,7 +65,7 @@ interface IDWriteFontFace;
 #endif
 
 #if USE(DIRECT2D)
-#include <dwrite.h>
+#include <dwrite_3.h>
 #endif
 
 namespace WebCore {
@@ -103,7 +103,7 @@ public:
 #endif
 
 #if PLATFORM(WIN) && USE(DIRECT2D)
-    FontPlatformData(GDIObject<HFONT>, IDWriteFont*, float size, bool syntheticBold, bool syntheticOblique, bool useGDI);
+    FontPlatformData(GDIObject<HFONT>&&, IDWriteFont*, float size, bool syntheticBold, bool syntheticOblique, bool useGDI);
 #endif
 
 #if PLATFORM(WIN) && USE(CAIRO)
@@ -145,6 +145,7 @@ public:
     IDWriteFontFace* dwFontFace() const { return m_dwFontFace.get(); }
 
     static HRESULT createFallbackFont(const LOGFONT&, IDWriteFont**);
+    static HRESULT createFallbackFont(HFONT, IDWriteFont**);
 #endif
 
     bool isFixedPitch() const;
index f7d0ac8..115c823 100644 (file)
 
 #include "SharedBuffer.h"
 
+#if USE(DIRECT2D)
+#include "DirectWriteUtilities.h"
+#include <dwrite_3.h>
+#endif
+
 namespace WebCore {
 
 struct BigEndianUShort { 
@@ -423,6 +428,11 @@ HANDLE renameAndActivateFont(const SharedBuffer& fontData, const String& fontNam
         return 0;
     }
 
+#if USE(DIRECT2D)
+    HRESULT hr = DirectWrite::addFontFromDataToProcessCollection(rewrittenFontData);
+    ASSERT(SUCCEEDED(hr));
+#endif
+
     return fontHandle;
 }
 
index 90baddf..12d2449 100644 (file)
@@ -34,6 +34,8 @@ interface IWICBitmap;
 
 namespace WebCore {
 
+class IntSize;
+
 class BackingStoreBackendDirect2DImpl final : public BackingStoreBackendDirect2D {
 public:
     WEBCORE_EXPORT BackingStoreBackendDirect2DImpl(const IntSize&, float deviceScaleFactor);
diff --git a/Source/WebCore/platform/graphics/win/DirectWriteUtilities.cpp b/Source/WebCore/platform/graphics/win/DirectWriteUtilities.cpp
new file mode 100644 (file)
index 0000000..1f0ff07
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2019 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DirectWriteUtilities.h"
+
+#if USE(DIRECT2D)
+
+#include "COMPtr.h"
+#include "SharedBuffer.h"
+#include <dwrite_3.h>
+
+
+namespace WebCore {
+
+namespace DirectWrite {
+
+IDWriteFactory5* factory()
+{
+    static IDWriteFactory5* directWriteFactory = nullptr;
+    if (!directWriteFactory) {
+        HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(directWriteFactory), reinterpret_cast<IUnknown**>(&directWriteFactory));
+        directWriteFactory->AddRef();
+        RELEASE_ASSERT(SUCCEEDED(hr));
+    }
+
+    return directWriteFactory;
+}
+
+IDWriteGdiInterop* gdiInterop()
+{
+    static IDWriteGdiInterop* directWriteGdiInterop = nullptr;
+    if (!directWriteGdiInterop) {
+        HRESULT hr = factory()->GetGdiInterop(&directWriteGdiInterop);
+        directWriteGdiInterop->AddRef();
+        RELEASE_ASSERT(SUCCEEDED(hr));
+    }
+
+    return directWriteGdiInterop;
+}
+
+static IDWriteInMemoryFontFileLoader* memoryFontLoader()
+{
+    static IDWriteInMemoryFontFileLoader* memoryFontLoader = nullptr;
+    if (!memoryFontLoader) {
+        HRESULT hr = factory()->CreateInMemoryFontFileLoader(&memoryFontLoader);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+        memoryFontLoader->AddRef();
+
+        hr = factory()->RegisterFontFileLoader(memoryFontLoader);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+    }
+
+    return memoryFontLoader;
+}
+
+static IDWriteFontSetBuilder1* fontSetBuilder()
+{
+    static IDWriteFontSetBuilder1* fontSetBuilder = nullptr;
+    if (!fontSetBuilder) {
+        HRESULT hr = factory()->CreateFontSetBuilder(&fontSetBuilder);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+        fontSetBuilder->AddRef();
+    }
+
+    return fontSetBuilder;
+}
+
+static COMPtr<IDWriteFontSet> fontSet;
+static COMPtr<IDWriteFontCollection1> fontCollection;
+static UINT32 fontCount = 0;
+
+IDWriteFontCollection1* webProcessFontCollection()
+{
+    HRESULT hr = S_OK;
+
+    if (!fontSet) {
+        hr = fontSetBuilder()->CreateFontSet(&fontSet);
+        if (!SUCCEEDED(hr))
+            return nullptr;
+
+        fontCollection = nullptr;
+        hr = factory()->CreateFontCollectionFromFontSet(fontSet.get(), &fontCollection);
+        if (!SUCCEEDED(hr))
+            return nullptr;
+
+        ASSERT(fontCollection->GetFontFamilyCount() == fontCount);
+    }
+
+    return fontCollection.get();
+}
+
+HRESULT addFontFromDataToProcessCollection(const Vector<char>& fontData)
+{
+    COMPtr<IDWriteFontFile> fontFile;
+    HRESULT hr = memoryFontLoader()->CreateInMemoryFontFileReference(factory(), fontData.data(), fontData.size(), nullptr, &fontFile);
+    if (!SUCCEEDED(hr))
+        return hr;
+
+    hr = fontSetBuilder()->AddFontFile(fontFile.get());
+    if (!SUCCEEDED(hr))
+        return hr;
+
+    fontSet = nullptr;
+    ++fontCount;
+
+    return hr;
+}
+
+Vector<wchar_t> familyNameForLocale(IDWriteFontFamily* fontFamily, const Vector<wchar_t>& localeName)
+{
+    COMPtr<IDWriteLocalizedStrings> familyNames;
+    HRESULT hr = fontFamily->GetFamilyNames(&familyNames);
+    if (FAILED(hr))
+        return { };
+
+    BOOL exists = false;
+    unsigned localeIndex = 0;
+    if (!localeName.isEmpty())
+        hr = familyNames->FindLocaleName(localeName.data(), &localeIndex, &exists);
+
+    if (SUCCEEDED(hr) && !exists)
+        hr = familyNames->FindLocaleName(L"en-us", &localeIndex, &exists);
+
+    if (FAILED(hr))
+        return { };
+
+    unsigned familyNameLength = 0;
+    hr = familyNames->GetStringLength(localeIndex, &familyNameLength);
+    if (!SUCCEEDED(hr))
+        return { };
+
+    Vector<wchar_t> familyName(familyNameLength + 1);
+    hr = familyNames->GetString(localeIndex, familyName.data(), familyName.size());
+    if (!SUCCEEDED(hr))
+        return { };
+
+    return familyName;
+}
+
+COMPtr<IDWriteFontFamily> fontFamilyForCollection(IDWriteFontCollection* fontCollection, const Vector<wchar_t>& localeName, const LOGFONT& logFont)
+{
+    COMPtr<IDWriteFontFamily> fontFamily;
+
+    unsigned fontFamilyCount = fontCollection->GetFontFamilyCount();
+    for (unsigned fontIndex = 0; fontIndex < fontFamilyCount; ++fontIndex) {
+        HRESULT hr = fontCollection->GetFontFamily(fontIndex, &fontFamily);
+        if (FAILED(hr))
+            return nullptr;
+
+        auto familyName = familyNameForLocale(fontFamily.get(), localeName);
+
+        if (!wcscmp(logFont.lfFaceName, familyName.data()))
+            return fontFamily;
+
+        fontFamily = nullptr;
+    }
+
+    return nullptr;
+}
+
+COMPtr<IDWriteFont> createWithPlatformFont(const LOGFONT& logFont)
+{
+    COMPtr<IDWriteFontCollection> systemFontCollection;
+    HRESULT hr = factory()->GetSystemFontCollection(&systemFontCollection);
+    if (FAILED(hr))
+        return nullptr;
+
+    Vector<wchar_t> localeName(LOCALE_NAME_MAX_LENGTH);
+    int localeLength = GetUserDefaultLocaleName(localeName.data(), LOCALE_NAME_MAX_LENGTH);
+
+    COMPtr<IDWriteFontFamily> fontFamily = fontFamilyForCollection(systemFontCollection.get(), localeName, logFont);
+    if (!fontFamily)
+        fontFamily = fontFamilyForCollection(webProcessFontCollection(), localeName, logFont);
+
+    if (!fontFamily) {
+        // Just return the first system font.
+        hr = systemFontCollection->GetFontFamily(0, &fontFamily);
+        if (FAILED(hr))
+            return nullptr;
+
+#ifndef NDEBUG
+        auto familyName = familyNameForLocale(fontFamily.get(), localeName);
+        UNUSED_VARIABLE(familyName);
+#endif
+    }
+
+    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;
+
+    COMPtr<IDWriteFont> dwFont;
+    hr = fontFamily->GetFirstMatchingFont(weight, stretch, style, &dwFont);
+    ASSERT(SUCCEEDED(hr));
+
+    return dwFont;
+}
+
+} // namespace DirectWrite
+
+} // namespace WebCore
+
+#endif // USE(DIRECT2D)
diff --git a/Source/WebCore/platform/graphics/win/DirectWriteUtilities.h b/Source/WebCore/platform/graphics/win/DirectWriteUtilities.h
new file mode 100644 (file)
index 0000000..ae50f84
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if USE(DIRECT2D)
+
+#include "COMPtr.h"
+
+interface IDWriteFactory5;
+interface IDWriteFont;
+interface IDWriteFontCollection;
+interface IDWriteFontCollection1;
+interface IDWriteFontFamily;
+interface IDWriteGdiInterop;
+
+namespace WebCore {
+
+class SharedBuffer;
+
+namespace DirectWrite {
+
+IDWriteFactory5* factory();
+IDWriteGdiInterop* gdiInterop();
+
+IDWriteFontCollection1* webProcessFontCollection();
+
+HRESULT addFontFromDataToProcessCollection(const Vector<char>& fontData);
+COMPtr<IDWriteFontFamily> fontFamilyForCollection(IDWriteFontCollection*, const Vector<wchar_t>& localeName, const LOGFONT&);
+COMPtr<IDWriteFont> createWithPlatformFont(const LOGFONT&);
+Vector<wchar_t> familyNameForLocale(IDWriteFontFamily*, const Vector<wchar_t>& localeName);
+
+} // namespace DirectWrite
+
+} // namespace WebCore
+
+#endif // USE(DIRECT2D)
index d31a257..d089d0f 100644 (file)
@@ -47,7 +47,7 @@
 #endif
 
 #if USE(DIRECT2D)
-#include <dwrite.h>
+#include <dwrite_3.h>
 #endif
 
 using std::min;
@@ -506,7 +506,7 @@ static GDIObject<HFONT> createGDIFont(const AtomString& family, LONG desiredWeig
     matchData.m_chosen.lfUnderline = false;
     matchData.m_chosen.lfStrikeOut = false;
     matchData.m_chosen.lfCharSet = DEFAULT_CHARSET;
-#if USE(CG) || USE(CAIRO)
+#if USE(CG) || USE(CAIRO) || USE(DIRECT2D)
     matchData.m_chosen.lfOutPrecision = OUT_TT_ONLY_PRECIS;
 #else
     matchData.m_chosen.lfOutPrecision = OUT_TT_PRECIS;
index 877d6e3..91112d9 100644 (file)
@@ -40,7 +40,7 @@
 #include "UniscribeController.h"
 #include "WebCoreTextRenderer.h"
 #include <d2d1.h>
-#include <dwrite.h>
+#include <dwrite_3.h>
 #include <wtf/MathExtras.h>
 
 namespace WebCore {
index 387a239..c829daa 100644 (file)
@@ -34,8 +34,8 @@
 #endif
 
 #if USE(DIRECT2D)
-#include "Font.h"
-#include <dwrite.h>
+#include "DirectWriteUtilities.h"
+#include <dwrite_3.h>
 #endif
 
 namespace WebCore {
@@ -65,7 +65,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription&
     logFont.lfUnderline = false;
     logFont.lfStrikeOut = false;
     logFont.lfCharSet = DEFAULT_CHARSET;
-#if USE(CG) || USE(CAIRO)
+#if USE(CG) || USE(CAIRO) || USE(DIRECT2D)
     logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
 #else
     logFont.lfOutPrecision = OUT_TT_PRECIS;
@@ -76,20 +76,11 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription&
     logFont.lfWeight = bold ? 700 : 400;
 
     auto hfont = adoptGDIObject(::CreateFontIndirect(&logFont));
-
 #if USE(CG)
     RetainPtr<CGFontRef> cgFont = adoptCF(CGFontCreateWithPlatformFont(&logFont));
     return FontPlatformData(WTFMove(hfont), cgFont.get(), size, bold, italic, renderingMode == FontRenderingMode::Alternate);
 #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));
+    COMPtr<IDWriteFont> dwFont = DirectWrite::createWithPlatformFont(logFont);
     return FontPlatformData(WTFMove(hfont), dwFont.get(), size, bold, italic, renderingMode == FontRenderingMode::Alternate);
 #endif
 }
index 8c144ae..a70c5f9 100644 (file)
 
 #if USE(DIRECT2D)
 
+#include "DirectWriteUtilities.h"
 #include "GraphicsContext.h"
+#include "HWndDC.h"
 #include "SharedGDIObject.h"
 #include <d2d1.h>
-#include <dwrite.h>
+#include <dwrite_3.h>
 #include <wtf/Vector.h>
 
 namespace WebCore {
@@ -39,24 +41,19 @@ namespace WebCore {
 void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName)
 {
     LOGFONT logfont;
-    GetObject(font, sizeof(logfont), &logfont);
-
-    HRESULT hr = Font::systemDWriteGdiInterop()->CreateFontFromLOGFONT(&logfont, &m_dwFont);
-    if (!SUCCEEDED(hr)) {
-        hr = FontPlatformData::createFallbackFont(logfont, &m_dwFont);
-        if (!SUCCEEDED(hr))
-            return;
-    }
+    HRESULT hr = ::GetObject(font, sizeof(LOGFONT), &logfont);
+    if (SUCCEEDED(hr))
+        m_dwFont = DirectWrite::createWithPlatformFont(logfont);
+    RELEASE_ASSERT(m_dwFont);
 
     hr = m_dwFont->CreateFontFace(&m_dwFontFace);
-    if (!SUCCEEDED(hr))
-        return;
+    RELEASE_ASSERT(SUCCEEDED(hr));
 
     if (!m_useGDI)
         m_isSystemFont = !wcscmp(faceName, L"Lucida Grande");
 }
 
-FontPlatformData::FontPlatformData(GDIObject<HFONT> hfont, IDWriteFont* font, float size, bool bold, bool oblique, bool useGDI)
+FontPlatformData::FontPlatformData(GDIObject<HFONT>&& hfont, IDWriteFont* font, float size, bool bold, bool oblique, bool useGDI)
     : m_syntheticBold(bold)
     , m_syntheticOblique(oblique)
     , m_size(size)
@@ -124,67 +121,48 @@ HRESULT FontPlatformData::createFallbackFont(const LOGFONT& logFont, IDWriteFont
     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);
+    *dwFont = DirectWrite::createWithPlatformFont(logFont).get();
 
-        if (FAILED(hr))
-            return hr;
+    return S_OK;
+}
 
-        unsigned familyNameLength = 0;
-        hr = familyNames->GetStringLength(localeIndex, &familyNameLength);
-        if (!SUCCEEDED(hr))
-            return hr;
+HRESULT FontPlatformData::createFallbackFont(HFONT hfont, IDWriteFont** dwFont)
+{
+    if (!dwFont)
+        return E_POINTER;
 
-        Vector<wchar_t> familyName(familyNameLength + 1);
-        hr = familyNames->GetString(localeIndex, familyName.data(), familyName.size());
-        if (!SUCCEEDED(hr))
-            return hr;
+    COMPtr<IDWriteFontCollection> fontCollection;
+    HRESULT hr = DirectWrite::factory()->GetSystemFontCollection(&fontCollection);
+    if (FAILED(hr))
+        return hr;
 
-        if (!wcscmp(logFont.lfFaceName, familyName.data()))
-            break;
+    HWndDC hdc(0);
+    HGDIOBJ oldFont = ::SelectObject(hdc, hfont);
 
-        fontFamily = nullptr;
+    COMPtr<IDWriteFontFace> fontFace;
+    hr = DirectWrite::gdiInterop()->CreateFontFaceFromHdc(hdc, &fontFace);
+    if (FAILED(hr)) {
+        ::SelectObject(hdc, oldFont);
+        return hr;
     }
 
-    if (!fontFamily) {
-        hr = fontCollection->GetFontFamily(0, &fontFamily);
-        if (FAILED(hr))
-            return hr;
+    LOGFONT gdiBasedFont = { };
+    hr = DirectWrite::gdiInterop()->ConvertFontFaceToLOGFONT(fontFace.get(), &gdiBasedFont);
+    if (FAILED(hr)) {
+        ::SelectObject(hdc, oldFont);
+        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 = fontCollection->GetFontFromFontFace(fontFace.get(), dwFont);
 
-    hr = fontFamily->GetFirstMatchingFont(weight, stretch, style, dwFont);
+    if (!SUCCEEDED(hr))
+        hr = DirectWrite::webProcessFontCollection()->GetFontFromFontFace(fontFace.get(), dwFont);
+
+    ::SelectObject(hdc, oldFont);
+    if (SUCCEEDED(hr))
+        return hr;
 
-    return hr;
+    return createFallbackFont(gdiBasedFont, dwFont);
 }
 
 }
index 6f5f6af..e5373c7 100644 (file)
@@ -34,7 +34,7 @@
 #include <wtf/text/WTFString.h>
 
 #if USE(DIRECT2D)
-#include <dwrite.h>
+#include <dwrite_3.h>
 #endif
 
 using std::min;
index eb700f4..72e25ff 100644 (file)
 
 #if USE(DIRECT2D)
 
+#include "DirectWriteUtilities.h"
 #include "Font.h"
 #include "TextAnalyzerHelper.h"
-#include <dwrite.h>
+#include <dwrite_3.h>
 
 namespace WebCore {
 
@@ -43,7 +44,7 @@ bool GlyphPage::fill(UChar* buffer, unsigned bufferLength)
     bool haveGlyphs = false;
 
     COMPtr<IDWriteTextAnalyzer> analyzer;
-    HRESULT hr = Font::systemDWriteFactory()->CreateTextAnalyzer(&analyzer);
+    HRESULT hr = DirectWrite::factory()->CreateTextAnalyzer(&analyzer);
     RELEASE_ASSERT(SUCCEEDED(hr));
 
     auto& fontPlatformData = font.platformData();
index c2bafaf..9f2d388 100644 (file)
@@ -38,7 +38,7 @@
 #include "PlatformContextDirect2D.h"
 #include <d2d1.h>
 #include <d2d1effects.h>
-#include <dwrite.h>
+#include <dwrite_3.h>
 #include <wtf/URL.h>
 
 #pragma warning (disable : 4756)
index c6a00f3..8aae9ea 100644 (file)
@@ -28,6 +28,7 @@
 
 #if USE(DIRECT2D)
 
+#include "DirectWriteUtilities.h"
 #include "FloatRect.h"
 #include "FontCache.h"
 #include "FontDescription.h"
@@ -36,7 +37,7 @@
 #include "HWndDC.h"
 #include "NotImplemented.h"
 #include <comutil.h>
-#include <dwrite.h>
+#include <dwrite_3.h>
 #include <mlang.h>
 #include <unicode/uchar.h>
 #include <unicode/unorm.h>
 
 namespace WebCore {
 
-IDWriteFactory* Font::systemDWriteFactory()
-{
-    static IDWriteFactory* directWriteFactory = nullptr;
-    if (!directWriteFactory) {
-        HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(directWriteFactory), reinterpret_cast<IUnknown**>(&directWriteFactory));
-        RELEASE_ASSERT(SUCCEEDED(hr));
-    }
-
-    return directWriteFactory;
-}
-
-IDWriteGdiInterop* Font::systemDWriteGdiInterop()
-{
-    static IDWriteGdiInterop* directWriteGdiInterop = nullptr;
-    if (!directWriteGdiInterop) {
-        HRESULT hr = systemDWriteFactory()->GetGdiInterop(&directWriteGdiInterop);
-        RELEASE_ASSERT(SUCCEEDED(hr));
-    }
-
-    return directWriteGdiInterop;
-}
-
 static Vector<WCHAR> getFaceName(IDWriteFont* font)
 {
     if (!font)
index 34571e0..eca332a 100644 (file)
 #include <wtf/MathExtras.h>
 #include <wtf/win/GDIObject.h>
 
-#if USE(DIRECT2D)
-#include <dwrite.h>
-#endif
-
 namespace WebCore {
 
 static bool g_shouldApplyMacAscentHack;