diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 93b4ed75980a..2f257594b668 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -37,24 +37,29 @@ namespace { sal::systools::COMReference -getDWritePrivateFontCollection_w10(IDWriteFontFile* fontFile) +getDWritePrivateFontCollection(IDWriteFontFace* fontFace) { + UINT32 numberOfFiles; + sal::systools::ThrowIfFailed(fontFace->GetFiles(&numberOfFiles, nullptr), SAL_WHERE); + if (numberOfFiles != 1) + return {}; + + sal::systools::COMReference fontFile; + sal::systools::ThrowIfFailed(fontFace->GetFiles(&numberOfFiles, &fontFile), SAL_WHERE); + static sal::systools::COMReference dwriteFactory3 = [] { IDWriteFactory* dwriteFactory = WinSalGraphics::getDWriteFactory(); sal::systools::COMReference factory3; - dwriteFactory->QueryInterface(&factory3); + sal::systools::ThrowIfFailed(dwriteFactory->QueryInterface(&factory3), SAL_WHERE); return factory3; }(); - if (!dwriteFactory3) - return {}; static sal::systools::COMReference dwriteFontSetBuilder = [] { sal::systools::COMReference builder; - dwriteFactory3->CreateFontSetBuilder(&dwriteFontSetBuilder); + sal::systools::ThrowIfFailed(dwriteFactory3->CreateFontSetBuilder(&dwriteFontSetBuilder), + SAL_WHERE); return builder; }(); - if (!dwriteFontSetBuilder) - return {}; BOOL isSupported; DWRITE_FONT_FILE_TYPE fileType; @@ -84,163 +89,6 @@ getDWritePrivateFontCollection_w10(IDWriteFontFile* fontFile) SAL_WHERE); return { fc1.get() }; } - -// The following is only needed until we bump baseline to Windows 10 - -template requires std::is_base_of_v class IUnknown_Impl : public I -{ -public: - virtual ~IUnknown_Impl() {} - - // IUnknown - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject) override - { - if (iid == IID_IUnknown || iid == __uuidof(I)) - { - *ppvObject = this; - AddRef(); - return S_OK; - } - - *ppvObject = nullptr; - return E_NOINTERFACE; - } - ULONG STDMETHODCALLTYPE AddRef() override { return ++m_nRef; } - ULONG STDMETHODCALLTYPE Release() override - { - ULONG n = --m_nRef; - if (n == 0) - delete this; - return n; - }; - -private: - std::atomic m_nRef = 0; -}; - -// A simple loader class, which only stores the font files (to fulfill the requirement that -// "each key is ... valid until the loader is unregistered using the factory"), and creates -// instances of enumerator -class FontCollectionLoader_w7 : public IUnknown_Impl -{ -public: - // IDWriteFontCollectionLoader - HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey( - IDWriteFactory* factory, void const* collectionKey, UINT32 collectionKeySize, - /* OUT */ IDWriteFontFileEnumerator** fontFileEnumerator) override; - -private: - std::vector> m_fontFiles; -}; - -// A singleton class, that (1) caches IDWriteFactory, to avoid destruction order problems, -// (2) holds the FontCollectionLoader_w7 singleton, and (3) calls IDWriteFactory's -// (Un)RegisterFontCollectionLoader, because these can't be called from destructor of -// FontCollectionLoader_w7, because RegisterFontCollectionLoader calls AddRef. -struct FontCollectionLoader_w7_singleton_t -{ - sal::systools::COMReference factory; - sal::systools::COMReference loader; - FontCollectionLoader_w7_singleton_t() - : factory(WinSalGraphics::getDWriteFactory()) - , loader(new FontCollectionLoader_w7) - { - factory->RegisterFontCollectionLoader(loader); - } - ~FontCollectionLoader_w7_singleton_t() { factory->UnregisterFontCollectionLoader(loader); } -}; - -// A simple enumerator class, which only operates on a single font file. -class FontFileEnumerator_w7 : public IUnknown_Impl -{ -public: - FontFileEnumerator_w7(IDWriteFontFile* collectionKey) - : m_fontFile(collectionKey) - { - assert(collectionKey); - AddRef(); - } - - // IDWriteFontFileEnumerator - HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile) override; - HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile) override; - -private: - sal::systools::COMReference m_fontFile; - size_t m_nextIndex = 0; -}; - -HRESULT STDMETHODCALLTYPE FontCollectionLoader_w7::CreateEnumeratorFromKey( - IDWriteFactory* /*factory*/, void const* collectionKey, UINT32 collectionKeySize, - /* OUT */ IDWriteFontFileEnumerator** fontFileEnumerator) -{ - if (!fontFileEnumerator) - return E_INVALIDARG; - *fontFileEnumerator = nullptr; - if (!collectionKey || collectionKeySize != sizeof(IDWriteFontFile*)) - return E_INVALIDARG; - - auto pFontFile = *static_cast(collectionKey); - auto it = std::find_if(m_fontFiles.begin(), m_fontFiles.end(), - [pFontFile](const auto& el) { return el.get() == pFontFile; }); - if (it == m_fontFiles.end()) - m_fontFiles.emplace_back(pFontFile); // cals AddRef - - *fontFileEnumerator = new (std::nothrow) FontFileEnumerator_w7(pFontFile); - return *fontFileEnumerator ? S_OK : E_OUTOFMEMORY; -} - -HRESULT STDMETHODCALLTYPE FontFileEnumerator_w7::MoveNext(BOOL* hasCurrentFile) -{ - if (!hasCurrentFile) - return E_INVALIDARG; - *hasCurrentFile = m_nextIndex == 0 ? TRUE : FALSE; - ++m_nextIndex; - return S_OK; -} - -HRESULT STDMETHODCALLTYPE FontFileEnumerator_w7::GetCurrentFontFile(IDWriteFontFile** fontFile) -{ - if (!fontFile) - return E_INVALIDARG; - if (m_nextIndex == 1) - { - *fontFile = m_fontFile; - m_fontFile->AddRef(); - return S_OK; - } - *fontFile = nullptr; - return E_FAIL; -} - -sal::systools::COMReference -getDWritePrivateFontCollection_w7(IDWriteFontFile* fontFile) -{ - static FontCollectionLoader_w7_singleton_t singleton; - sal::systools::COMReference collection; - sal::systools::ThrowIfFailed(singleton.factory->CreateCustomFontCollection( - singleton.loader, &fontFile, sizeof(fontFile), &collection), - SAL_WHERE); - return collection; -} - -// End of pre-Windows 10 compatibility code - -sal::systools::COMReference -getDWritePrivateFontCollection(IDWriteFontFace* fontFace) -{ - UINT32 numberOfFiles; - sal::systools::ThrowIfFailed(fontFace->GetFiles(&numberOfFiles, nullptr), SAL_WHERE); - if (numberOfFiles != 1) - return {}; - - sal::systools::COMReference fontFile; - sal::systools::ThrowIfFailed(fontFace->GetFiles(&numberOfFiles, &fontFile), SAL_WHERE); - - if (auto collection = getDWritePrivateFontCollection_w10(fontFile)) - return collection; - return getDWritePrivateFontCollection_w7(fontFile); -} } using namespace SkiaHelper; @@ -363,6 +211,8 @@ WinSkiaSalGraphicsImpl::createDirectWriteTypeface(const WinFontInstance* pWinFon // private fonts with this newly used font. dwritePrivateCollection = getDWritePrivateFontCollection(fontFace); + if (!dwritePrivateCollection) // Not one file? Unsupported font? + return nullptr; ThrowIfFailed(dwritePrivateCollection->GetFontFromFontFace(fontFace, &font), SAL_WHERE); } }