summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2022-01-02 21:55:10 +0000
committerCaolán McNamara <caolanm@redhat.com>2022-01-11 18:11:23 +0100
commit68818db0ec0e9c308c8a0772d46af551f439b32c (patch)
tree18befac2baed205b762c23a379e0eb4cc7bca910
parentf242cc6d5be5c6f5446976fd6a7c26ad0cee7683 (diff)
build a IDWriteFontCollection1 of our FR_PRIVATE fonts
so we don't need to fallback to gdi in skia for those we build it incrementally as GetFontFromFontFace fails in the system font set Change-Id: I2ac6d151657b9b720eed46dd7bcee0e9682e462a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127877 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--vcl/inc/skia/win/gdiimpl.hxx4
-rw-r--r--vcl/skia/win/gdiimpl.cxx70
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;