diff options
-rw-r--r-- | RepositoryExternal.mk | 1 | ||||
-rw-r--r-- | external/skia/UnpackedTarball_skia.mk | 1 | ||||
-rw-r--r-- | external/skia/fontconfig-get-typeface.patch.0 | 32 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 3 | ||||
-rw-r--r-- | vcl/Library_vclplug_gen.mk | 9 | ||||
-rw-r--r-- | vcl/inc/skia/gdiimpl.hxx | 3 | ||||
-rw-r--r-- | vcl/inc/skia/x11/textrender.hxx | 40 | ||||
-rw-r--r-- | vcl/inc/unx/fc_fontoptions.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/unx/glyphcache.hxx | 4 | ||||
-rw-r--r-- | vcl/skia/gdiimpl.cxx | 44 | ||||
-rw-r--r-- | vcl/skia/x11/textrender.cxx | 79 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/cairotextrender.cxx | 14 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/salgdi.cxx | 5 | ||||
-rw-r--r-- | vcl/unx/generic/glyphs/freetype_glyphcache.cxx | 18 |
14 files changed, 234 insertions, 21 deletions
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk index a0de7e340de8..7079e9bcf61b 100644 --- a/RepositoryExternal.mk +++ b/RepositoryExternal.mk @@ -127,6 +127,7 @@ $(call gb_LinkTarget_set_include,$(1),\ -I$(call gb_UnpackedTarball_get_dir,skia)/include/effects \ -I$(call gb_UnpackedTarball_get_dir,skia)/include/gpu \ -I$(call gb_UnpackedTarball_get_dir,skia)/include/config \ + -I$(call gb_UnpackedTarball_get_dir,skia)/include/ports \ -I$(call gb_UnpackedTarball_get_dir,skia)/include/third_party/vulkan \ -I$(call gb_UnpackedTarball_get_dir,skia)/tools/gpu \ -I$(call gb_UnpackedTarball_get_dir,skia) \ diff --git a/external/skia/UnpackedTarball_skia.mk b/external/skia/UnpackedTarball_skia.mk index 33fcf05b6a81..6ffde2006590 100644 --- a/external/skia/UnpackedTarball_skia.mk +++ b/external/skia/UnpackedTarball_skia.mk @@ -27,6 +27,7 @@ skia_patches := \ fix-gcc-x86.patch.1 \ msvc-vectorcall-sse.patch.1 \ clang11-flax-vector-conversion.patch.0 \ + fontconfig-get-typeface.patch.0 \ $(eval $(call gb_UnpackedTarball_set_patchlevel,skia,1)) diff --git a/external/skia/fontconfig-get-typeface.patch.0 b/external/skia/fontconfig-get-typeface.patch.0 new file mode 100644 index 000000000000..a7a82bfa07f4 --- /dev/null +++ b/external/skia/fontconfig-get-typeface.patch.0 @@ -0,0 +1,32 @@ +--- ./src/ports/SkFontMgr_fontconfig.cpp.sav 2020-01-20 16:42:51.322186451 +0100 ++++ ./src/ports/SkFontMgr_fontconfig.cpp 2020-03-13 11:25:15.793936659 +0100 +@@ -699,6 +699,7 @@ class SkFontMgr_fontconfig : public SkFo + /** Creates a typeface using a typeface cache. + * @param pattern a complete pattern from FcFontRenderPrepare. + */ ++public: + sk_sp<SkTypeface> createTypefaceFromFcPattern(FcPattern* pattern) const { + FCLocker::AssertHeld(); + SkAutoMutexExclusive ama(fTFCacheMutex); +@@ -1039,3 +1040,9 @@ protected: + SK_API sk_sp<SkFontMgr> SkFontMgr_New_FontConfig(FcConfig* fc) { + return sk_make_sp<SkFontMgr_fontconfig>(fc); + } ++ ++SK_API sk_sp<SkTypeface> SkFontMgr_createTypefaceFromFcPattern(const sk_sp<SkFontMgr>& mgr, FcPattern* pattern) ++{ ++ FCLocker lock; ++ return static_cast<SkFontMgr_fontconfig*>(mgr.get())->createTypefaceFromFcPattern(pattern); ++} +--- ./include/ports/SkFontMgr_fontconfig.h.sav 2019-09-19 11:38:00.943185323 +0200 ++++ ./include/ports/SkFontMgr_fontconfig.h 2020-03-13 11:31:48.025716543 +0100 +@@ -19,4 +19,9 @@ class SkFontMgr; + */ + SK_API sk_sp<SkFontMgr> SkFontMgr_New_FontConfig(FcConfig* fc); + ++struct _FcPattern; ++typedef struct _FcPattern FcPattern; ++class SkTypeface; ++SK_API sk_sp<SkTypeface> SkFontMgr_createTypefaceFromFcPattern(const sk_sp<SkFontMgr>& mgr, FcPattern* pattern); ++ + #endif // #ifndef SkFontMgr_fontconfig_DEFINED diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 9becb8efc977..39d99957883e 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -599,7 +599,8 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/skia/packedsurfaceatlas \ vcl/skia/salbmp \ vcl/skia/zone \ - vcl/skia/gdiimpl) \ + vcl/skia/gdiimpl \ + ) \ )) # runtime dependency diff --git a/vcl/Library_vclplug_gen.mk b/vcl/Library_vclplug_gen.mk index 500783ed67e1..34ca4df4ba50 100644 --- a/vcl/Library_vclplug_gen.mk +++ b/vcl/Library_vclplug_gen.mk @@ -60,7 +60,10 @@ $(eval $(call gb_Library_use_externals,vclplug_gen,\ icuuc \ valgrind \ Xrender \ - $(if $(filter SKIA,$(BUILD_TYPE)),skia) \ + $(if $(filter SKIA,$(BUILD_TYPE)), \ + skia \ + fontconfig \ + ) \ )) $(eval $(call gb_Library_add_libs,vclplug_gen,\ @@ -111,7 +114,9 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gen,\ $(if $(filter SKIA,$(BUILD_TYPE)), \ vcl/skia/x11/cairotextrender \ vcl/skia/x11/gdiimpl \ - vcl/skia/x11/salvd) \ + vcl/skia/x11/salvd \ + vcl/skia/x11/textrender \ + ) \ )) # ultimately we want to split the x11 dependencies out diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 46b3f7bcd334..a7de1cfc4872 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -32,6 +32,7 @@ #include <postwin.h> class SkiaFlushIdle; +class GenericSalLayout; class VCL_DLLPUBLIC SkiaSalGraphicsImpl : public SalGraphicsImpl { @@ -202,6 +203,8 @@ public: void drawBitmap(const SalTwoRect& rPosAry, const SkBitmap& aBitmap, SkBlendMode eBlendMode = SkBlendMode::kSrcOver); + void drawGenericLayout(const GenericSalLayout& layout, Color textColor, const SkFont& font); + protected: // To be called before any drawing. void preDraw(); diff --git a/vcl/inc/skia/x11/textrender.hxx b/vcl/inc/skia/x11/textrender.hxx new file mode 100644 index 000000000000..2aeda63cfb5c --- /dev/null +++ b/vcl/inc/skia/x11/textrender.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_SKIA_TEXTRENDER_HXX +#define INCLUDED_VCL_INC_SKIA_TEXTRENDER_HXX + +#include <unx/freetypetextrender.hxx> + +#include <SkFontMgr.h> +#include <SkFontMgr_fontconfig.h> + +class VCL_DLLPUBLIC SkiaTextRender : public FreeTypeTextRenderImpl +{ +public: + virtual void DrawTextLayout(const GenericSalLayout&, const SalGraphics&) override; + virtual void ClearDevFontCache() override; + +private: + sk_sp<SkFontMgr> fontManager; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/unx/fc_fontoptions.hxx b/vcl/inc/unx/fc_fontoptions.hxx index fe1bbef20452..de6ed2aba5df 100644 --- a/vcl/inc/unx/fc_fontoptions.hxx +++ b/vcl/inc/unx/fc_fontoptions.hxx @@ -23,7 +23,7 @@ #include <rtl/string.hxx> typedef struct _FcPattern FcPattern; -class FontConfigFontOptions +class VCL_DLLPUBLIC FontConfigFontOptions { public: FontConfigFontOptions(FcPattern* pPattern) : diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx index d2352a4ffd44..38c51a036a1b 100644 --- a/vcl/inc/unx/glyphcache.hxx +++ b/vcl/inc/unx/glyphcache.hxx @@ -136,7 +136,7 @@ private: FontFileList m_aFontFileList; }; -class FreetypeFont final +class VCL_DLLPUBLIC FreetypeFont final { public: ~FreetypeFont(); @@ -169,7 +169,7 @@ public: // in starmath at a fairly low stretch ratio. This appears fixed in 2.9 with // https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?id=91015cb41d8f56777f93394f5a60914bc0c0f330 // "Improve complex rendering at high ppem" - static bool AlmostHorizontalDrainsRenderingPool(); + static bool AlmostHorizontalDrainsRenderingPool(int nRatio, const FontSelectPattern& rFSD); private: friend class FreetypeManager; diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 7dfd667e8a63..3bf0724de354 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -33,6 +33,8 @@ #include <SkRegion.h> #include <SkDashPathEffect.h> #include <GrBackendSurface.h> +#include <SkTextBlob.h> +#include <SkRSXform.h> #include <numeric> #include <basegfx/polygon/b2dpolygontools.hxx> @@ -1258,6 +1260,48 @@ bool SkiaSalGraphicsImpl::drawGradient(const tools::PolyPolygon&, const Gradient return false; } +static double toRadian(int degree10th) { return (3600 - degree10th) * M_PI / 1800.0; } +static double toCos(int degree10th) { return SkScalarCos(toRadian(degree10th)); } +static double toSin(int degree10th) { return SkScalarSin(toRadian(degree10th)); } + +void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Color textColor, + const SkFont& font) +{ + std::vector<SkGlyphID> glyphIds; + std::vector<SkRSXform> glyphForms; + glyphIds.reserve(256); + glyphForms.reserve(256); + Point aPos; + const GlyphItem* pGlyph; + int nStart = 0; + double orientationAngle = layout.GetOrientation(); // 10th of degree + while (layout.GetNextGlyph(&pGlyph, aPos, nStart)) + { + glyphIds.push_back(pGlyph->glyphId()); + double angle = orientationAngle; + if (pGlyph->IsVertical()) + angle += 900; // 90 degree + SkRSXform form = SkRSXform::Make(toCos(angle), toSin(angle), aPos.X(), aPos.Y()); + glyphForms.emplace_back(std::move(form)); + } + if (glyphIds.empty()) + return; + sk_sp<SkTextBlob> textBlob + = SkTextBlob::MakeFromRSXform(glyphIds.data(), glyphIds.size() * sizeof(SkGlyphID), + glyphForms.data(), font, SkTextEncoding::kGlyphID); + preDraw(); + SAL_INFO("vcl.skia", "drawtextblob(" + << this << "): " + << tools::Rectangle(textBlob->bounds().x(), textBlob->bounds().y(), + textBlob->bounds().width(), + textBlob->bounds().height()) + << ":" << textColor); + SkPaint paint; + paint.setColor(toSkColor(textColor)); + getDrawCanvas()->drawTextBlob(textBlob, 0, 0, paint); + postDraw(); +} + bool SkiaSalGraphicsImpl::supportsOperation(OutDevSupportType eType) const { switch (eType) diff --git a/vcl/skia/x11/textrender.cxx b/vcl/skia/x11/textrender.cxx new file mode 100644 index 000000000000..02911fcf5154 --- /dev/null +++ b/vcl/skia/x11/textrender.cxx @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <skia/x11/textrender.hxx> + +#include <unx/fc_fontoptions.hxx> +#include <unx/freetype_glyphcache.hxx> +#include <vcl/svapp.hxx> +#include <sallayout.hxx> +#include <skia/gdiimpl.hxx> + +#include <SkFont.h> +#include <SkFontMgr_fontconfig.h> + +void SkiaTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalGraphics& rGraphics) +{ + const FreetypeFontInstance& rInstance = static_cast<FreetypeFontInstance&>(rLayout.GetFont()); + const FreetypeFont& rFont = *rInstance.GetFreetypeFont(); + const FontSelectPattern& rFSD = rInstance.GetFontSelectPattern(); + int nHeight = rFSD.mnHeight; + int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight; + if (nWidth == 0 || nHeight == 0) + return; + + if (FreetypeFont::AlmostHorizontalDrainsRenderingPool(nWidth * 10 / nHeight, rFSD)) + return; + + if (!fontManager) + { + // Get the global FcConfig that our VCL fontconfig code uses, and refcount it. + fontManager = SkFontMgr_New_FontConfig(FcConfigReference(nullptr)); + } + sk_sp<SkTypeface> typeface + = SkFontMgr_createTypefaceFromFcPattern(fontManager, rFont.GetFontOptions()->GetPattern()); + SkFont font(typeface, nHeight); + // TODO are these correct? + if (rFont.NeedsArtificialItalic()) + font.setSkewX(-0x6000L / 0x10000L); + if (rFont.NeedsArtificialBold()) + font.setEmbolden(true); + font.setEdging(rFont.GetAntialiasAdvice() ? SkFont::Edging::kAntiAlias + : SkFont::Edging::kAlias); + + assert(dynamic_cast<SkiaSalGraphicsImpl*>(rGraphics.GetImpl())); + SkiaSalGraphicsImpl* impl = static_cast<SkiaSalGraphicsImpl*>(rGraphics.GetImpl()); + impl->drawGenericLayout(rLayout, mnTextColor, font); +} + +void SkiaTextRender::ClearDevFontCache() { fontManager.reset(); } + +#if 0 +// SKIA TODO +void FontConfigFontOptions::cairo_font_options_substitute(FcPattern* pPattern) +{ + ImplSVData* pSVData = ImplGetSVData(); + const cairo_font_options_t* pFontOptions = pSVData->mpDefInst->GetCairoFontOptions(); + if( !pFontOptions ) + return; + cairo_ft_font_options_substitute(pFontOptions, pPattern); +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx index 36ed2cb6bed2..8276029db557 100644 --- a/vcl/unx/generic/gdi/cairotextrender.cxx +++ b/vcl/unx/generic/gdi/cairotextrender.cxx @@ -148,20 +148,8 @@ void CairoTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalG return; int nRatio = nWidth * 10 / nHeight; - if (nRatio > 100 && rFSD.maTargetName == "OpenSymbol" && FreetypeFont::AlmostHorizontalDrainsRenderingPool()) - { - // tdf#127189 FreeType <= 2.8 will fail to render stretched horizontal - // brace glyphs in starmath at a fairly low stretch ratio. The failure - // will set CAIRO_STATUS_FREETYPE_ERROR on the surface which cannot be - // cleared, so all further painting to the surface fails. - - // This appears fixed in >= freetype 2.9 - - // Restrict this bodge to a stretch ratio > ~10 of the OpenSymbol font - // where it has been seen in practice. - SAL_WARN("vcl", "rendering text would fail with stretch ratio of: " << nRatio << ", with FreeType <= 2.8"); + if (FreetypeFont::AlmostHorizontalDrainsRenderingPool(nRatio, rFSD)) return; - } /* * It might be ideal to cache surface and cairo context between calls and diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx index d5b6281bed3b..16a7c40046b9 100644 --- a/vcl/unx/generic/gdi/salgdi.cxx +++ b/vcl/unx/generic/gdi/salgdi.cxx @@ -59,6 +59,7 @@ #if HAVE_FEATURE_SKIA #include <skia/x11/gdiimpl.hxx> #include <skia/x11/cairotextrender.hxx> +#include <skia/x11/textrender.hxx> #endif X11SalGraphics::X11SalGraphics(): @@ -86,7 +87,11 @@ X11SalGraphics::X11SalGraphics(): if (m_bSkia) { mxImpl.reset(new X11SkiaSalGraphicsImpl(*this)); +#if 1 + mxTextRenderImpl.reset(new SkiaTextRender); +#else // old method, probably can be removed once native Skia render works well mxTextRenderImpl.reset(new SkiaX11CairoTextRender(*this)); +#endif } else #endif diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx index 7408b5f780d4..08a8521b5627 100644 --- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx +++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx @@ -308,10 +308,24 @@ namespace } } -bool FreetypeFont::AlmostHorizontalDrainsRenderingPool() +bool FreetypeFont::AlmostHorizontalDrainsRenderingPool(int nRatio, const FontSelectPattern& rFSD) { static bool bAlmostHorizontalDrainsRenderingPool = DoesAlmostHorizontalDrainRenderingPool(); - return bAlmostHorizontalDrainsRenderingPool; + if (nRatio > 100 && rFSD.maTargetName == "OpenSymbol" && bAlmostHorizontalDrainsRenderingPool) + { + // tdf#127189 FreeType <= 2.8 will fail to render stretched horizontal + // brace glyphs in starmath at a fairly low stretch ratio. The failure + // will set CAIRO_STATUS_FREETYPE_ERROR on the surface which cannot be + // cleared, so all further painting to the surface fails. + + // This appears fixed in >= freetype 2.9 + + // Restrict this bodge to a stretch ratio > ~10 of the OpenSymbol font + // where it has been seen in practice. + SAL_WARN("vcl", "rendering text would fail with stretch ratio of: " << nRatio << ", with FreeType <= 2.8"); + return true; + } + return false; } FT_Face FreetypeFont::GetFtFace() const |