[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