diff options
-rw-r--r-- | vcl/inc/skia/win/gdiimpl.hxx | 4 | ||||
-rw-r--r-- | vcl/skia/win/gdiimpl.cxx | 70 |
2 files changed, 68 insertions, 6 deletions
diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 58043e5f6a83..a8897d0d7c20 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -25,6 +25,8 @@ #include <SkFont.h> #include <SkFontMgr.h> +#include <dwrite_3.h> + class SkTypeface; class ControlCacheKey; @@ -64,6 +66,8 @@ protected: static void initFontInfo(); inline static sal::systools::COMReference<IDWriteFactory> dwriteFactory; inline static sal::systools::COMReference<IDWriteGdiInterop> dwriteGdiInterop; + inline static sal::systools::COMReference<IDWriteFontSetBuilder> dwriteFontSetBuilder; + inline static sal::systools::COMReference<IDWriteFontCollection1> dwritePrivateCollection; inline static sk_sp<SkFontMgr> dwriteFontMgr; inline static bool dwriteDone = false; static SkFont::Edging fontEdging; diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index a10351888eac..6686ecd0e8ed 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -163,11 +163,7 @@ sk_sp<SkTypeface> WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO // different version of the same font installed system-wide). // For that CreateFromFaceFromHdc() is necessary. The simpler // CreateFontFromLOGFONT() seems to search for the best matching font, - // which may not be the exact font. Our private fonts are installed - // using AddFontResourceExW( FR_PRIVATE ) and that apparently does - // not make them available to DirectWrite (at least, they are not - // included the DWrite system font collection). For such cases, we'll - // need to fall back to Skia's GDI-based font rendering. + // which may not be the exact font. HFONT oldFont = SelectFont(hdc, hfont); sal::systools::COMReference<IDWriteFontFace> fontFace; if (FAILED(CHECKHR(dwriteGdiInterop->CreateFontFaceFromHdc(hdc, &fontFace)))) @@ -175,6 +171,7 @@ sk_sp<SkTypeface> WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO SelectFont(hdc, oldFont); return nullptr; } + SelectFont(hdc, oldFont); sal::systools::COMReference<IDWriteFontCollection> collection; if (FAILED(CHECKHR(dwriteFactory->GetSystemFontCollection(&collection)))) @@ -182,7 +179,66 @@ sk_sp<SkTypeface> WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO sal::systools::COMReference<IDWriteFont> font; // Do not use CHECKHR() here, as said above, this fails for our fonts. if (FAILED(collection->GetFontFromFontFace(fontFace.get(), &font))) - return nullptr; + { + // If not found in system collection, try our private font collection. + // If that's not possible we'll fall back to Skia's GDI-based font rendering. + if (!dwritePrivateCollection + || FAILED(dwritePrivateCollection->GetFontFromFontFace(fontFace.get(), &font))) + { + // Our private fonts are installed using AddFontResourceExW( FR_PRIVATE ) + // and that does not make them available to the DWrite system font + // collection. For such cases attempt to update a collection of + // private fonts with this newly used font. + + sal::systools::COMReference<IDWriteFactory3> dwriteFactory3; + if (FAILED(dwriteFactory->QueryInterface<IDWriteFactory3>(&dwriteFactory3))) + return nullptr; + + if (!dwriteFontSetBuilder + && FAILED(dwriteFactory3->CreateFontSetBuilder(&dwriteFontSetBuilder))) + return nullptr; + + UINT32 numberOfFiles; + if (FAILED(fontFace->GetFiles(&numberOfFiles, nullptr)) || numberOfFiles != 1) + return nullptr; + + sal::systools::COMReference<IDWriteFontFile> fontFile; + if (FAILED(fontFace->GetFiles(&numberOfFiles, &fontFile))) + return nullptr; + + BOOL isSupported; + DWRITE_FONT_FILE_TYPE fileType; + UINT32 numberOfFonts; + if (FAILED(fontFile->Analyze(&isSupported, &fileType, nullptr, &numberOfFonts)) + || !isSupported) + return nullptr; + + // For each font within the font file, get a font face reference and add to the builder. + for (UINT32 fontIndex = 0; fontIndex < numberOfFonts; ++fontIndex) + { + sal::systools::COMReference<IDWriteFontFaceReference> fontFaceReference; + if (FAILED(dwriteFactory3->CreateFontFaceReference(fontFile.get(), fontIndex, + DWRITE_FONT_SIMULATIONS_NONE, + &fontFaceReference))) + continue; + + // Leave it to DirectWrite to read properties directly out of the font files + dwriteFontSetBuilder->AddFontFaceReference(fontFaceReference.get()); + } + + dwritePrivateCollection.clear(); + sal::systools::COMReference<IDWriteFontSet> fontSet; + if (SUCCEEDED(CHECKHR(dwriteFontSetBuilder->CreateFontSet(&fontSet)))) + dwriteFactory3->CreateFontCollectionFromFontSet(fontSet.get(), + &dwritePrivateCollection); + } + + if (!dwritePrivateCollection) + return nullptr; + // CHECKHR because we expect to succeed here + if (FAILED(CHECKHR(dwritePrivateCollection->GetFontFromFontFace(fontFace.get(), &font)))) + return nullptr; + } sal::systools::COMReference<IDWriteFontFamily> fontFamily; if (FAILED(CHECKHR(font->GetFontFamily(&fontFamily)))) return nullptr; @@ -296,6 +352,8 @@ void WinSkiaSalGraphicsImpl::initFontInfo() void WinSkiaSalGraphicsImpl::ClearDevFontCache() { dwriteFontMgr.reset(); + dwriteFontSetBuilder.clear(); + dwritePrivateCollection.clear(); dwriteFactory.clear(); dwriteGdiInterop.clear(); dwriteDone = false; |