[Libreoffice-commits] core.git: external/skia vcl/inc vcl/skia vcl/win

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Fri Apr 10 13:17:09 UTC 2020


 external/skia/UnpackedTarball_skia.mk              |    1 
 external/skia/windows-text-gamma.patch.0           |   42 +++++++++
 external/skia/windows-typeface-directwrite.patch.0 |   48 +++++++++++
 vcl/inc/skia/win/gdiimpl.hxx                       |   13 +++
 vcl/inc/win/wingdiimpl.hxx                         |    2 
 vcl/skia/win/gdiimpl.cxx                           |   91 ++++++++++++++++++---
 vcl/win/gdi/salfont.cxx                            |    4 
 7 files changed, 191 insertions(+), 10 deletions(-)

New commits:
commit 894c0806328627aadd1e92c8601a5858a3ea627f
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Thu Apr 9 12:19:07 2020 +0100
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Fri Apr 10 15:16:34 2020 +0200

    prefer DirectWrite for Skia's Windows text rendering
    
    Change-Id: Ibfb6206751126def10905bb22effbe1a947cd6d6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91968
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lunak at collabora.com>

diff --git a/external/skia/UnpackedTarball_skia.mk b/external/skia/UnpackedTarball_skia.mk
index da0a2a7a0547..82fdbc433ece 100644
--- a/external/skia/UnpackedTarball_skia.mk
+++ b/external/skia/UnpackedTarball_skia.mk
@@ -33,6 +33,7 @@ skia_patches := \
     operator-eq-bool.patch.0 \
     fix-without-gl.patch.0 \
     extend-rgb-to-rgba.patch.0 \
+    windows-typeface-directwrite.patch.0 \
 
 $(eval $(call gb_UnpackedTarball_set_patchlevel,skia,1))
 
diff --git a/external/skia/windows-text-gamma.patch.0 b/external/skia/windows-text-gamma.patch.0
index 366b67f15a65..624636b7da99 100644
--- a/external/skia/windows-text-gamma.patch.0
+++ b/external/skia/windows-text-gamma.patch.0
@@ -26,3 +26,45 @@
              RGBToLcd16<false>(src, srcRB, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
          }
      }
+--- ./src/ports/SkScalerContext_win_dw.cpp
++++ ./src/ports/SkScalerContext_win_dw.cpp
+@@ -1132,27 +1132,36 @@ void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
+         BilevelToBW(src, glyph);
+     } else if (!isLCD(fRec)) {
+         if (textureType == DWRITE_TEXTURE_ALIASED_1x1) {
++#if defined(SK_GAMMA_APPLY_TO_A8)
+             if (fPreBlend.isApplicable()) {
+                 GrayscaleToA8<true>(src, glyph, fPreBlend.fG);
+-            } else {
++            } else
++#endif
++            {
+                 GrayscaleToA8<false>(src, glyph, fPreBlend.fG);
+             }
+         } else {
++#if defined(SK_GAMMA_APPLY_TO_A8)
+             if (fPreBlend.isApplicable()) {
+                 RGBToA8<true>(src, glyph, fPreBlend.fG);
+-            } else {
++            } else
++#endif
++            {
+                 RGBToA8<false>(src, glyph, fPreBlend.fG);
+             }
+         }
+     } else {
+         SkASSERT(SkMask::kLCD16_Format == glyph.fMaskFormat);
++#if defined(SK_GAMMA_APPLY_TO_A8)
+         if (fPreBlend.isApplicable()) {
+             if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) {
+                 RGBToLcd16<true, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+             } else {
+                 RGBToLcd16<true, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+             }
+-        } else {
++        } else
++#endif
++        {
+             if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) {
+                 RGBToLcd16<false, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+             } else {
diff --git a/external/skia/windows-typeface-directwrite.patch.0 b/external/skia/windows-typeface-directwrite.patch.0
new file mode 100644
index 000000000000..56e8209cedb4
--- /dev/null
+++ b/external/skia/windows-typeface-directwrite.patch.0
@@ -0,0 +1,48 @@
+--- ./include/ports/SkTypeface_win.h
++++ ./include/ports/SkTypeface_win.h
+@@ -75,5 +75,13 @@ SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWriteRenderer(sk_sp<SkRemotableFontM
+  */
+ SK_API sk_sp<SkRemotableFontMgr> SkRemotableFontMgr_New_DirectWrite();
+ 
++struct IDWriteFontFace;
++struct IDWriteFont;
++struct IDWriteFontFamily;
++SK_API SkTypeface* SkCreateTypefaceDirectWrite(sk_sp<SkFontMgr> fontMgr,
++                                               IDWriteFontFace* fontFace,
++                                               IDWriteFont* font,
++                                               IDWriteFontFamily* fontFamily);
++
+ #endif  // SK_BUILD_FOR_WIN
+ #endif  // SkTypeface_win_DEFINED
+--- ./src/ports/SkFontMgr_win_dw.cpp
++++ ./src/ports/SkFontMgr_win_dw.cpp
+@@ -320,6 +320,10 @@ private:
+ 
+     friend class SkFontStyleSet_DirectWrite;
+     friend class FontFallbackRenderer;
++    friend SK_API SkTypeface* SkCreateTypefaceDirectWrite(sk_sp<SkFontMgr> fontMgr,
++                                               IDWriteFontFace* fontFace,
++                                               IDWriteFont* font,
++                                               IDWriteFontFamily* fontFamily);
+ };
+ 
+ class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
+@@ -1215,6 +1219,18 @@ SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWrite(IDWriteFactory* factory,
+                                              defaultFamilyName, defaultFamilyNameLen);
+ }
+ 
++SkTypeface* SkCreateTypefaceDirectWrite(sk_sp<SkFontMgr> fontMgr,
++                                        IDWriteFontFace* fontFace,
++                                        IDWriteFont* font,
++                                        IDWriteFontFamily* fontFamily)
++{
++    SkFontMgr_DirectWrite* mgr = dynamic_cast<SkFontMgr_DirectWrite*>(fontMgr.get());
++    if(!mgr)
++        return nullptr;
++    sk_sp<SkTypeface> typeface = mgr->makeTypefaceFromDWriteFont(fontFace, font, fontFamily);
++    return typeface.release();
++}
++
+ #include "include/ports/SkFontMgr_indirect.h"
+ SK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWriteRenderer(sk_sp<SkRemotableFontMgr> proxy) {
+     sk_sp<SkFontMgr> impl(SkFontMgr_New_DirectWrite());
diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx
index 3d6c680f2af4..c16981abcb23 100644
--- a/vcl/inc/skia/win/gdiimpl.hxx
+++ b/vcl/inc/skia/win/gdiimpl.hxx
@@ -21,6 +21,10 @@
 #include <ControlCacheKey.hxx>
 #include <svdata.hxx>
 
+#include <SkFont.h>
+
+class SkTypeface;
+class SkFontMgr;
 class ControlCacheKey;
 
 class SkiaCompatibleDC : public CompatibleDC
@@ -83,12 +87,21 @@ public:
                               const SalTwoRect& rPosAry) override;
     virtual void DeferredTextDraw(const CompatibleDC::Texture* pTexture, Color nMaskColor,
                                   const SalTwoRect& rPosAry) override;
+    virtual void ClearDevFontCache() override;
 
     static void prepareSkia();
 
 protected:
     virtual void createWindowContext() override;
     virtual void performFlush() override;
+    sk_sp<SkTypeface> createDirectWriteTypeface(const LOGFONTW& logFont);
+    SkFont::Edging getFontEdging();
+    IDWriteFactory* dwriteFactory;
+    IDWriteGdiInterop* dwriteGdiInterop;
+    sk_sp<SkFontMgr> dwriteFontMgr;
+    bool dwriteDone = false;
+    SkFont::Edging fontEdging;
+    bool fontEdgingDone = false;
 };
 
 typedef std::pair<ControlCacheKey, sk_sp<SkImage>> SkiaControlCachePair;
diff --git a/vcl/inc/win/wingdiimpl.hxx b/vcl/inc/win/wingdiimpl.hxx
index e81e35201413..679be2c36588 100644
--- a/vcl/inc/win/wingdiimpl.hxx
+++ b/vcl/inc/win/wingdiimpl.hxx
@@ -35,6 +35,8 @@ public:
         abort();
     };
 
+    virtual void ClearDevFontCache(){};
+
     // Implementation for WinSalGraphics::DrawTextLayout().
     // Returns true if handled, if false, then WinSalGraphics will handle it itself.
     virtual bool DrawTextLayout(const GenericSalLayout&) { return false; }
diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx
index 42c9078316f2..7bf150a6ccee 100644
--- a/vcl/skia/win/gdiimpl.cxx
+++ b/vcl/skia/win/gdiimpl.cxx
@@ -14,6 +14,7 @@
 #include <skia/utils.hxx>
 #include <skia/zone.hxx>
 #include <win/winlayout.hxx>
+#include <comphelper/windowserrorstring.hxx>
 
 #include <SkCanvas.h>
 #include <SkColorFilter.h>
@@ -21,6 +22,7 @@
 #include <SkPixelRef.h>
 #include <SkTypeface_win.h>
 #include <SkFont.h>
+#include <SkFontMgr.h>
 #include <tools/sk_app/win/WindowContextFactory_win.h>
 #include <tools/sk_app/WindowContext.h>
 
@@ -111,6 +113,55 @@ bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite, C
     return true;
 }
 
+#ifdef SAL_LOG_WARN
+HRESULT checkResult(HRESULT hr, const char* file, size_t line)
+{
+    if (FAILED(hr))
+    {
+        OUString sLocationString
+            = OUString::createFromAscii(file) + ":" + OUString::number(line) + " ";
+        SAL_DETAIL_LOG_STREAM(SAL_DETAIL_ENABLE_LOG_WARN, ::SAL_DETAIL_LOG_LEVEL_WARN, "vcl.skia",
+                              sLocationString.toUtf8().getStr(),
+                              "HRESULT failed with: 0x" << OUString::number(hr, 16) << ": "
+                                                        << WindowsErrorStringFromHRESULT(hr));
+    }
+    return hr;
+}
+
+#define CHECKHR(funct) checkResult(funct, __FILE__, __LINE__)
+#else
+#define CHECKHR(funct) (funct)
+#endif
+
+sk_sp<SkTypeface> WinSkiaSalGraphicsImpl::createDirectWriteTypeface(const LOGFONTW& logFont)
+{
+    if (!dwriteDone)
+    {
+        IDWriteFactory* factory;
+        if (SUCCEEDED(
+                CHECKHR(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
+                                            reinterpret_cast<IUnknown**>(&factory)))))
+        {
+            if (SUCCEEDED(CHECKHR(factory->GetGdiInterop(&dwriteGdiInterop))))
+                dwriteFontMgr = SkFontMgr_New_DirectWrite(dwriteFactory);
+            else
+                factory->Release();
+        }
+        dwriteDone = true;
+    }
+    IDWriteFont* font = nullptr;
+    IDWriteFontFace* fontFace;
+    IDWriteFontFamily* fontFamily;
+    if (FAILED(CHECKHR(dwriteGdiInterop->CreateFontFromLOGFONT(&logFont, &font))))
+        return nullptr;
+    if (FAILED(CHECKHR(font->CreateFontFace(&fontFace))))
+        return nullptr;
+    if (FAILED(CHECKHR(font->GetFontFamily(&fontFamily))))
+        return nullptr;
+    return sk_sp<SkTypeface>(
+        SkCreateTypefaceDirectWrite(dwriteFontMgr, fontFace, font, fontFamily));
+}
+
 bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout)
 {
     const WinFontInstance& rWinFont = static_cast<const WinFontInstance&>(rLayout.GetFont());
@@ -125,7 +176,9 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout)
         assert(false);
         return false;
     }
-    sk_sp<SkTypeface> typeface(SkCreateTypefaceFromLOGFONT(logFont));
+    sk_sp<SkTypeface> typeface = createDirectWriteTypeface(logFont);
+    if (!typeface) // fall back to GDI text rendering
+        typeface.reset(SkCreateTypefaceFromLOGFONT(logFont));
     // lfHeight actually depends on DPI, so it's not really font height as such,
     // but for LOGFONT-based typefaces Skia simply sets lfHeight back to this value
     // directly.
@@ -133,6 +186,20 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout)
     if (fontHeight < 0)
         fontHeight = -fontHeight;
     SkFont font(typeface, fontHeight, fHScale, 0);
+    font.setEdging(getFontEdging());
+    assert(dynamic_cast<SkiaSalGraphicsImpl*>(mWinParent.GetImpl()));
+    SkiaSalGraphicsImpl* impl = static_cast<SkiaSalGraphicsImpl*>(mWinParent.GetImpl());
+    COLORREF color = ::GetTextColor(mWinParent.getHDC());
+    Color salColor(GetRValue(color), GetGValue(color), GetBValue(color));
+    // The font already is set up to have glyphs rotated as needed.
+    impl->drawGenericLayout(rLayout, salColor, font, SkiaSalGraphicsImpl::GlyphOrientation::Ignore);
+    return true;
+}
+
+SkFont::Edging WinSkiaSalGraphicsImpl::getFontEdging()
+{
+    if (fontEdgingDone)
+        return fontEdging;
     // Skia needs to be explicitly told what kind of antialiasing should be used,
     // get it from system settings. This does not actually matter for the text
     // rendering itself, since Skia has been patched to simply use the setting
@@ -141,23 +208,27 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout)
     // the appropriate AA setting. But Skia internally chooses the format to which
     // the glyphs will be rendered based on this setting (subpixel AA requires colors,
     // others do not).
+    fontEdging = SkFont::Edging::kAlias;
     BOOL set;
     if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &set, 0) && set)
     {
         UINT set2;
         if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &set2, 0)
             && set2 == FE_FONTSMOOTHINGCLEARTYPE)
-            font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
+            fontEdging = SkFont::Edging::kSubpixelAntiAlias;
         else
-            font.setEdging(SkFont::Edging::kAntiAlias);
+            fontEdging = SkFont::Edging::kAntiAlias;
     }
-    assert(dynamic_cast<SkiaSalGraphicsImpl*>(mWinParent.GetImpl()));
-    SkiaSalGraphicsImpl* impl = static_cast<SkiaSalGraphicsImpl*>(mWinParent.GetImpl());
-    COLORREF color = ::GetTextColor(mWinParent.getHDC());
-    Color salColor(GetRValue(color), GetGValue(color), GetBValue(color));
-    // The font already is set up to have glyphs rotated as needed.
-    impl->drawGenericLayout(rLayout, salColor, font, SkiaSalGraphicsImpl::GlyphOrientation::Ignore);
-    return true;
+    // Cache this, it is actually visible a little bit when profiling.
+    fontEdgingDone = true;
+    return fontEdging;
+}
+
+void WinSkiaSalGraphicsImpl::ClearDevFontCache()
+{
+    dwriteFontMgr.reset();
+    dwriteDone = false;
+    fontEdgingDone = false;
 }
 
 void WinSkiaSalGraphicsImpl::PreDrawText() { preDraw(); }
diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx
index 774178b683f8..cd7ca435e807 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -58,6 +58,7 @@
 #include <win/saldata.hxx>
 #include <win/salgdi.h>
 #include <win/winlayout.hxx>
+#include <win/wingdiimpl.hxx>
 #include <impfontcharmap.hxx>
 #include <impfontmetricdata.hxx>
 #include <impglyphitem.hxx>
@@ -1272,6 +1273,9 @@ void WinSalGraphics::GetDevFontList( PhysicalFontCollection* pFontCollection )
 
 void WinSalGraphics::ClearDevFontCache()
 {
+    WinSalGraphicsImplBase* pImpl = dynamic_cast<WinSalGraphicsImplBase*>(GetImpl());
+    assert(pImpl != nullptr);
+    pImpl->ClearDevFontCache();
     ImplReleaseTempFonts(*GetSalData(), false);
 }
 


More information about the Libreoffice-commits mailing list