diff options
34 files changed, 377 insertions, 450 deletions
diff --git a/bin/check-elf-dynamic-objects b/bin/check-elf-dynamic-objects index 5c484598b3b6..ea2d67e31ff4 100755 --- a/bin/check-elf-dynamic-objects +++ b/bin/check-elf-dynamic-objects @@ -133,10 +133,6 @@ local file="$1" ;; */libvcllo.so) whitelist="${whitelist} ${x11whitelist} ${openglwhitelist} ${giowhitelist} libcups.so.2" - if [ "$ENABLE_QT5" = TRUE ]; then - #TODO: is inclusion of vcl/qt5/Qt5Font.cxx in Library_vcl really wanted? - whitelist="${whitelist} ${qt5whitelist}" - fi ;; */libsofficeapp.so) whitelist="${whitelist} ${x11whitelist} ${openglwhitelist} ${giowhitelist} libcups.so.2" diff --git a/vcl/CppunitTest_vcl_fontmetric.mk b/vcl/CppunitTest_vcl_fontmetric.mk index 776064817ea1..70e2386e5f50 100644 --- a/vcl/CppunitTest_vcl_fontmetric.mk +++ b/vcl/CppunitTest_vcl_fontmetric.mk @@ -46,4 +46,8 @@ $(eval $(call gb_CppunitTest_use_components,vcl_fontmetric,\ $(eval $(call gb_CppunitTest_use_configuration,vcl_fontmetric)) +$(eval $(call gb_CppunitTest_use_externals,vcl_fontmetric,\ + harfbuzz \ +)) + # vim: set noet sw=4 ts=4: diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index b69fbfdd96f9..3da03f8acfbb 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -780,22 +780,4 @@ ifeq ($(OS),WNT) $(eval $(call gb_Library_use_package,vcl,postprocess_images)) endif -ifeq ($(ENABLE_QT5),TRUE) -$(eval $(call gb_Library_use_externals,vcl,\ - qt5 \ -)) -$(eval $(call gb_Library_add_defs,vcl,\ - $(QT5_CFLAGS) \ -)) -$(eval $(call gb_Library_add_libs,vcl,\ - $(QT5_LIBS) \ -)) -$(eval $(call gb_Library_add_cxxflags,vcl,\ - $(QT5_CFLAGS) \ -)) -$(eval $(call gb_Library_add_exception_objects,vcl,\ - vcl/qt5/Qt5Font \ -)) -endif - # vim: set noet sw=4 ts=4: diff --git a/vcl/Library_vclplug_kde4.mk b/vcl/Library_vclplug_kde4.mk index acd7bd5981da..88dfd50f41f7 100644 --- a/vcl/Library_vclplug_kde4.mk +++ b/vcl/Library_vclplug_kde4.mk @@ -52,6 +52,7 @@ $(eval $(call gb_Library_use_libraries,vclplug_kde4,\ $(eval $(call gb_Library_use_externals,vclplug_kde4,\ boost_headers \ + harfbuzz \ icuuc \ kde4 \ epoxy \ diff --git a/vcl/Library_vclplug_qt5.mk b/vcl/Library_vclplug_qt5.mk index 2a12414401dc..5245d8a0149b 100644 --- a/vcl/Library_vclplug_qt5.mk +++ b/vcl/Library_vclplug_qt5.mk @@ -80,8 +80,9 @@ endif $(eval $(call gb_Library_add_exception_objects,vclplug_qt5,\ vcl/qt5/Qt5Bitmap \ vcl/qt5/Qt5Data \ - vcl/qt5/Qt5Frame \ + vcl/qt5/Qt5Font \ vcl/qt5/Qt5FontFace \ + vcl/qt5/Qt5Frame \ vcl/qt5/Qt5Graphics \ vcl/qt5/Qt5Graphics_Controls \ vcl/qt5/Qt5Graphics_GDI \ diff --git a/vcl/inc/CommonSalLayout.hxx b/vcl/inc/CommonSalLayout.hxx index 6ad2627b129b..ae5804d5df95 100644 --- a/vcl/inc/CommonSalLayout.hxx +++ b/vcl/inc/CommonSalLayout.hxx @@ -20,85 +20,32 @@ #ifndef INCLUDED_VCL_INC_COMMONSALLAYOUT_HXX #define INCLUDED_VCL_INC_COMMONSALLAYOUT_HXX -#include <config_qt5.h> - #include <com/sun/star/i18n/XBreakIterator.hpp> -#ifdef _WIN32 -#include "win/winlayout.hxx" - -#elif defined(MACOSX) || defined(IOS) -#include "quartz/ctfonts.hxx" -#include <hb-coretext.h> - -#else -#include "unx/freetype_glyphcache.hxx" -#endif - #include "sallayout.hxx" -#include <hb-icu.h> -#include <hb-ot.h> +#include "fontinstance.hxx" -#if ENABLE_QT5 -class Qt5Font; -#endif +#include <hb-icu.h> class VCL_DLLPUBLIC CommonSalLayout : public GenericSalLayout { - hb_font_t* mpHbFont; - const FontSelectPattern& mrFontSelData; + LogicalFontInstance* const mpFont; css::uno::Reference<css::i18n::XBreakIterator> mxBreak; -#ifdef _WIN32 - HDC mhDC; - HFONT mhFont; - WinFontInstance& mrWinFontInstance; - double mnAveWidthFactor; -#elif defined(MACOSX) || defined(IOS) - const CoreTextStyle& mrCoreTextStyle; -#else - FreetypeFont* mpFreetypeFont; -#if ENABLE_QT5 - const bool mbUseQt5; - Qt5Font* mpQFont; - - explicit CommonSalLayout(const FontSelectPattern &rFSP, - FreetypeFont *pFreetypeFont, - Qt5Font *pFont, bool bUseQt5); -#endif - void InitFromFreetypeFont(); -#endif void ParseFeatures(const OUString& name); OString msLanguage; std::vector<hb_feature_t> maFeatures; - void getScale(double* nXScale, double* nYScale); - hb_set_t* mpVertGlyphs; - bool mbFuzzing; + const bool mbFuzzing; bool HasVerticalAlternate(sal_UCS4 aChar, sal_UCS4 aNextChar); void SetNeedFallback(ImplLayoutArgs&, sal_Int32, bool); public: -#if defined(_WIN32) - explicit CommonSalLayout(HDC, WinFontInstance&); - const FontSelectPattern& getFontSelData() const { return mrFontSelData; } - HFONT getHFONT() const { return mhFont; } - WinFontInstance& getWinFontInstance() const { return mrWinFontInstance; } - bool hasHScale() const; -#elif defined(MACOSX) || defined(IOS) - explicit CommonSalLayout(const CoreTextStyle&); - const CoreTextStyle& getFontData() const { return mrCoreTextStyle; } -#else - explicit CommonSalLayout(FreetypeFont&); - const FreetypeFont* getFreetypeFont() const { return mpFreetypeFont; } -#if ENABLE_QT5 - explicit CommonSalLayout(Qt5Font&); - const Qt5Font* getQt5Font() const { return mpQFont; } - bool useQt5() const { return mbUseQt5; } -#endif -#endif + CommonSalLayout(LogicalFontInstance&); + ~CommonSalLayout() override; + LogicalFontInstance& getFont() const { return *mpFont; } virtual void InitFont() const override; void AdjustLayout(ImplLayoutArgs&) final override; @@ -113,4 +60,5 @@ public: }; #endif // INCLUDED_VCL_INC_COMMONSALLAYOUT_HXX + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/fontinstance.hxx b/vcl/inc/fontinstance.hxx index c37ada563fb0..8bd6584c6154 100644 --- a/vcl/inc/fontinstance.hxx +++ b/vcl/inc/fontinstance.hxx @@ -26,6 +26,8 @@ #include <unordered_map> #include <memory> +#include <hb-ot.h> + class ConvertChar; class ImplFontCache; class PhysicalFontFace; @@ -57,13 +59,25 @@ public: // TODO: make data members private void Acquire(); void Release(); + inline hb_font_t* GetHbFont(); + void SetAverageWidthFactor(double nFactor) { m_nAveWidthFactor = nFactor; } + double GetAverageWidthFactor() const { return m_nAveWidthFactor; } const FontSelectPattern& GetFontSelectPattern() const { return m_aFontSelData; } + const PhysicalFontFace* GetFontFace() const { return m_pFontFace; } const ImplFontCache* GetFontCache() const { return mpFontCache; } + void GetScale(double* nXScale, double* nYScale); + static inline void DecodeOpenTypeTag(const uint32_t nTableTag, char* pTagName); + protected: explicit LogicalFontInstance(const PhysicalFontFace&, const FontSelectPattern&); + // Takes ownership of pHbFace. + hb_font_t* InitHbFont(hb_face_t* pHbFace) const; + virtual hb_font_t* ImplInitHbFont() { assert(false); return nullptr; } + inline void ReleaseHbFont(); + private: // cache of Unicode characters and replacement font names // TODO: a fallback map can be shared with many other ImplFontEntries @@ -73,9 +87,35 @@ private: ImplFontCache * mpFontCache; sal_uInt32 mnRefCount; const FontSelectPattern m_aFontSelData; + hb_font_t* m_pHbFont; + double m_nAveWidthFactor; const PhysicalFontFace* m_pFontFace; }; +inline hb_font_t* LogicalFontInstance::GetHbFont() +{ + if (!m_pHbFont) + m_pHbFont = ImplInitHbFont(); + return m_pHbFont; +} + +inline void LogicalFontInstance::ReleaseHbFont() +{ + if (!m_pHbFont) + return; + hb_font_destroy(m_pHbFont); + m_pHbFont = nullptr; +} + +inline void LogicalFontInstance::DecodeOpenTypeTag(const uint32_t nTableTag, char* pTagName) +{ + pTagName[0] = static_cast<char>(nTableTag >> 24); + pTagName[1] = static_cast<char>(nTableTag >> 16); + pTagName[2] = static_cast<char>(nTableTag >> 8); + pTagName[3] = static_cast<char>(nTableTag); + pTagName[4] = 0; +} + #endif // INCLUDED_VCL_INC_FONTINSTANCE_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h index 4d7fa35a0981..dbbbdee612e8 100644 --- a/vcl/inc/quartz/salgdi.h +++ b/vcl/inc/quartz/salgdi.h @@ -47,6 +47,8 @@ #include <unordered_map> #include <hb-ot.h> +#include "fontinstance.hxx" + class AquaSalFrame; class FontAttributes; class CoreTextStyle; @@ -63,6 +65,7 @@ public: PhysicalFontFace* Clone() const override; sal_IntPtr GetFontId() const override; + int GetFontTable( uint32_t nTagCode, unsigned char* ) const; int GetFontTable( const char pTagName[5], unsigned char* ) const; const FontCharMapRef GetFontCharMap() const; @@ -91,8 +94,6 @@ public: void GetFontMetric( ImplFontMetricDataRef const & ) const; bool GetGlyphBoundRect(const GlyphItem&, tools::Rectangle&) const; bool GetGlyphOutline(const GlyphItem&, basegfx::B2DPolyPolygon&) const; - hb_font_t* GetHbFont() const { return mpHbFont; } - void SetHbFont(hb_font_t* pHbFont) const { mpHbFont = pHbFont; } CFMutableDictionaryRef GetStyleDict( void ) const { return mpStyleDict; } @@ -104,9 +105,10 @@ public: private: explicit CoreTextStyle(const PhysicalFontFace&, const FontSelectPattern&); + virtual hb_font_t* ImplInitHbFont() override; + /// CoreText text style object CFMutableDictionaryRef mpStyleDict; - mutable hb_font_t* mpHbFont; }; // TODO: move into cross-platform headers diff --git a/vcl/inc/salwtype.hxx b/vcl/inc/salwtype.hxx index 1800b976aeb9..a7384090a20f 100644 --- a/vcl/inc/salwtype.hxx +++ b/vcl/inc/salwtype.hxx @@ -24,11 +24,11 @@ #include <rtl/ustring.hxx> #include <tools/solar.h> +class LogicalFontInstance; class SalGraphics; class SalFrame; class SalObject; namespace vcl { class Window; } -class FontSelectPattern; enum class InputContextFlags; enum class WindowStateMask; enum class WindowStateState; @@ -239,7 +239,7 @@ struct SalFrameState struct SalInputContext { - const FontSelectPattern* mpFont; + LogicalFontInstance* mpFont; LanguageType meLanguage; InputContextFlags mnOptions; }; diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx index 42300a1e56e2..09cd76695b62 100644 --- a/vcl/inc/svdata.hxx +++ b/vcl/inc/svdata.hxx @@ -31,7 +31,6 @@ #include <com/sun/star/i18n/XCharacterClassification.hpp> #include "vcleventlisteners.hxx" -#include "impfontcache.hxx" #include "salwtype.hxx" #include "displayconnectiondispatch.hxx" diff --git a/vcl/inc/unx/freetype_glyphcache.hxx b/vcl/inc/unx/freetype_glyphcache.hxx index fc1852db4f7c..0a7b88887b24 100644 --- a/vcl/inc/unx/freetype_glyphcache.hxx +++ b/vcl/inc/unx/freetype_glyphcache.hxx @@ -126,6 +126,8 @@ class VCL_DLLPUBLIC FreetypeFontInstance : public LogicalFontInstance FreetypeFont* mpFreetypeFont; + virtual hb_font_t* ImplInitHbFont() override; + protected: explicit FreetypeFontInstance(const PhysicalFontFace& rPFF, const FontSelectPattern& rFSP); diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx index ba56ecf48b75..7d507f100fe0 100644 --- a/vcl/inc/unx/glyphcache.hxx +++ b/vcl/inc/unx/glyphcache.hxx @@ -118,7 +118,7 @@ class VCL_DLLPUBLIC FreetypeFont final { public: FreetypeFont( const FontSelectPattern&, FreetypeFontInfo* ); - ~FreetypeFont(); + virtual ~FreetypeFont(); const OString& GetFontFileName() const; int GetFontFaceIndex() const; @@ -130,8 +130,6 @@ public: bool NeedsArtificialBold() const { return mbArtBold; } bool NeedsArtificialItalic() const { return mbArtItalic; } - const FontSelectPattern& GetFontSelData() const { return maFontSelData; } - void GetFontMetric(ImplFontMetricDataRef const &) const; const unsigned char* GetTable( const char* pName, sal_uLong* pLength ) const; const FontCharMapRef GetFontCharMap() const; @@ -140,8 +138,8 @@ public: const tools::Rectangle& GetGlyphBoundRect(const GlyphItem& rGlyph); bool GetGlyphOutline(const GlyphItem& rGlyph, basegfx::B2DPolyPolygon&) const; bool GetAntialiasAdvice() const; - hb_font_t* GetHbFont() { return mpHbFont; } - void SetHbFont( hb_font_t* pHbFont ) { mpHbFont = pHbFont; } + + LogicalFontInstance* GetFontInstance() const { return mpFontInstance; } private: friend class GlyphCache; @@ -163,7 +161,7 @@ private: typedef std::unordered_map<int,GlyphData> GlyphList; mutable GlyphList maGlyphList; - const FontSelectPattern maFontSelData; + LogicalFontInstance* const mpFontInstance; // used by GlyphCache for cache LRU algorithm mutable long mnRefCount; @@ -190,8 +188,6 @@ private: bool mbFaceOk; bool mbArtItalic; bool mbArtBold; - - hb_font_t* mpHbFont; }; #endif // INCLUDED_VCL_INC_GENERIC_GLYPHCACHE_HXX diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index cc30963d21c2..85b88e8e5f10 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -90,14 +90,9 @@ private: BYTE mnPitchAndFamily; bool mbAliasSymbolsHigh; bool mbAliasSymbolsLow; -private: + void ReadCmapTable( HDC ) const; void GetFontCapabilities( HDC hDC ) const; - - mutable hb_font_t* mpHbFont; -public: - hb_font_t* GetHbFont() const { return mpHbFont; } - void SetHbFont( hb_font_t* pHbFont ) const { mpHbFont = pHbFont; } }; /** Class that creates (and destroys) a compatible Device Context. diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx index 600817d8e2b8..ca0945949265 100644 --- a/vcl/inc/win/winlayout.hxx +++ b/vcl/inc/win/winlayout.hxx @@ -25,6 +25,7 @@ #include <sallayout.hxx> #include <svsys.h> #include <win/salgdi.h> +#include <CommonSalLayout.hxx> #include <opengl/PackedTextureAtlas.hxx> @@ -150,14 +151,20 @@ class WinFontInstance : public LogicalFontInstance public: virtual ~WinFontInstance() override; -public: bool CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, SalGraphics& rGraphics); GlyphCache& GetGlyphCache() { return maGlyphCache; } + bool hasHScale() const; + + void SetHDC(const HDC); + HFONT GetHFONT() const { return m_hFont; } private: explicit WinFontInstance(const PhysicalFontFace&, const FontSelectPattern&); - // TODO: also add HFONT??? Watch out for issues with too many active fonts... + virtual hb_font_t* ImplInitHbFont() override; + + HDC m_hDC; + HFONT m_hFont; GlyphCache maGlyphCache; }; diff --git a/vcl/qt5/Qt5Font.cxx b/vcl/qt5/Qt5Font.cxx index 01a45d359600..0164c3b13cd4 100644 --- a/vcl/qt5/Qt5Font.cxx +++ b/vcl/qt5/Qt5Font.cxx @@ -17,8 +17,37 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include <qt5/Qt5Font.hxx> +#include "Qt5Font.hxx" + +#include <QtGui/QFont> +#include <QtGui/QRawFont> + +Qt5Font::Qt5Font(const PhysicalFontFace& rPFF, const FontSelectPattern& rFSP) + : LogicalFontInstance(rPFF, rFSP) +{ +} Qt5Font::~Qt5Font() {} +static hb_blob_t* getFontTable(hb_face_t*, hb_tag_t nTableTag, void* pUserData) +{ + char pTagName[5]; + LogicalFontInstance::DecodeOpenTypeTag(nTableTag, pTagName); + + Qt5Font* pFont = static_cast<Qt5Font*>(pUserData); + QRawFont aRawFont(QRawFont::fromFont(*pFont)); + QByteArray aTable = aRawFont.fontTable(pTagName); + const sal_uInt32 nLength = aTable.size(); + + hb_blob_t* pBlob = nullptr; + if (nLength > 0) + pBlob = hb_blob_create(aTable.data(), nLength, HB_MEMORY_MODE_DUPLICATE, nullptr, nullptr); + return pBlob; +} + +hb_font_t* Qt5Font::ImplInitHbFont() +{ + return InitHbFont(hb_face_create_for_tables(getFontTable, this, nullptr)); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/qt5/Qt5Font.hxx b/vcl/qt5/Qt5Font.hxx index 1a1940fa7df0..fd496348c9b6 100644 --- a/vcl/inc/qt5/Qt5Font.hxx +++ b/vcl/qt5/Qt5Font.hxx @@ -19,26 +19,22 @@ #pragma once -#include <vcl/dllapi.h> +#include <fontinstance.hxx> + #include <QtGui/QFont> -#include <fontinstance.hxx> -#include <hb-ot.h> +#include "Qt5FontFace.hxx" -class VCL_DLLPUBLIC Qt5Font : public QFont, public LogicalFontInstance +class Qt5Font final : public QFont, public LogicalFontInstance { - hb_font_t* m_pHbFont; + friend LogicalFontInstance* Qt5FontFace::CreateFontInstance(const FontSelectPattern&) const; + + virtual hb_font_t* ImplInitHbFont() override; + + explicit Qt5Font(const PhysicalFontFace&, const FontSelectPattern&); public: - Qt5Font(const PhysicalFontFace& rPFF, const FontSelectPattern& rFSP) - : LogicalFontInstance(rPFF, rFSP) - , m_pHbFont(nullptr) - { - } virtual ~Qt5Font() override; - - hb_font_t* GetHbFont() const { return m_pHbFont; } - void SetHbFont(hb_font_t* pHbFont) { m_pHbFont = pHbFont; } }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/qt5/Qt5FontFace.cxx b/vcl/qt5/Qt5FontFace.cxx index dd80292922aa..0cd071385aaa 100644 --- a/vcl/qt5/Qt5FontFace.cxx +++ b/vcl/qt5/Qt5FontFace.cxx @@ -18,7 +18,7 @@ */ #include "Qt5FontFace.hxx" -#include <qt5/Qt5Font.hxx> +#include "Qt5Font.hxx" #include "Qt5Tools.hxx" #include <sft.hxx> diff --git a/vcl/qt5/Qt5Graphics.cxx b/vcl/qt5/Qt5Graphics.cxx index cf39b916ab42..8bf37adddff8 100644 --- a/vcl/qt5/Qt5Graphics.cxx +++ b/vcl/qt5/Qt5Graphics.cxx @@ -19,7 +19,7 @@ #include "Qt5Graphics.hxx" -#include <qt5/Qt5Font.hxx> +#include "Qt5Font.hxx" #include "Qt5Frame.hxx" #include "Qt5Painter.hxx" @@ -34,7 +34,6 @@ Qt5Graphics::Qt5Graphics( Qt5Frame *pFrame, QImage *pQImage ) , m_aFillColor( 0xFF, 0xFF, 0XFF ) , m_eCompositionMode( QPainter::CompositionMode_SourceOver ) , m_pFontCollection( nullptr ) - , m_pFontData{ nullptr, } , m_pTextStyle{ nullptr, } , m_aTextColor( 0x00, 0x00, 0x00 ) { diff --git a/vcl/qt5/Qt5Graphics.hxx b/vcl/qt5/Qt5Graphics.hxx index 9feff684ec93..8b37232f7e5c 100644 --- a/vcl/qt5/Qt5Graphics.hxx +++ b/vcl/qt5/Qt5Graphics.hxx @@ -48,7 +48,6 @@ class Qt5Graphics : public SalGraphics QPainter::CompositionMode m_eCompositionMode; PhysicalFontCollection* m_pFontCollection; - const Qt5FontFace* m_pFontData[MAX_FALLBACK]; Qt5Font* m_pTextStyle[MAX_FALLBACK]; Color m_aTextColor; diff --git a/vcl/qt5/Qt5Graphics_Text.cxx b/vcl/qt5/Qt5Graphics_Text.cxx index 4314e6333fe3..ed3d849aa3f4 100644 --- a/vcl/qt5/Qt5Graphics_Text.cxx +++ b/vcl/qt5/Qt5Graphics_Text.cxx @@ -19,7 +19,7 @@ #include "Qt5Graphics.hxx" #include "Qt5FontFace.hxx" -#include <qt5/Qt5Font.hxx> +#include "Qt5Font.hxx" #include <vcl/fontcharmap.hxx> @@ -78,16 +78,17 @@ void Qt5Graphics::GetFontMetric(ImplFontMetricDataRef& rFMD, int nFallbackLevel) const FontCharMapRef Qt5Graphics::GetFontCharMap() const { - if (!m_pFontData[0]) + if (!m_pTextStyle[0]) return FontCharMapRef(new FontCharMap()); - return m_pFontData[0]->GetFontCharMap(); + return static_cast<const Qt5FontFace*>(m_pTextStyle[0]->GetFontFace())->GetFontCharMap(); } bool Qt5Graphics::GetFontCapabilities(vcl::FontCapabilities& rFontCapabilities) const { - if (!m_pFontData[0]) + if (!m_pTextStyle[0]) return false; - return m_pFontData[0]->GetFontCapabilities(rFontCapabilities); + return static_cast<const Qt5FontFace*>(m_pTextStyle[0]->GetFontFace()) + ->GetFontCapabilities(rFontCapabilities); } void Qt5Graphics::GetDevFontList(PhysicalFontCollection* pPFC) diff --git a/vcl/quartz/ctfonts.cxx b/vcl/quartz/ctfonts.cxx index b35d121a314c..be615a1ee377 100644 --- a/vcl/quartz/ctfonts.cxx +++ b/vcl/quartz/ctfonts.cxx @@ -49,7 +49,6 @@ CoreTextStyle::CoreTextStyle(const PhysicalFontFace& rPFF, const FontSelectPatte , mfFontStretch( 1.0 ) , mfFontRotation( 0.0 ) , mpStyleDict( nullptr ) - , mpHbFont( nullptr ) { double fScaledFontHeight = rFSP.mfExactHeight; @@ -103,8 +102,6 @@ CoreTextStyle::~CoreTextStyle() { if( mpStyleDict ) CFRelease( mpStyleDict ); - if( mpHbFont ) - hb_font_destroy( mpHbFont ); } void CoreTextStyle::GetFontMetric( ImplFontMetricDataRef const & rxFontMetric ) const @@ -261,6 +258,42 @@ bool CoreTextStyle::GetGlyphOutline(const GlyphItem& rGlyph, basegfx::B2DPolyPol return true; } +static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) +{ + sal_uLong nLength = 0; + unsigned char* pBuffer = nullptr; + CoreTextFontFace* pFont = static_cast<CoreTextFontFace*>(pUserData); + nLength = pFont->GetFontTable(nTableTag, nullptr); + if (nLength > 0) + { + pBuffer = new unsigned char[nLength]; + pFont->GetFontTable(nTableTag, pBuffer); + } + + hb_blob_t* pBlob = nullptr; + if (pBuffer != nullptr) + pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY, + pBuffer, [](void* data){ delete[] static_cast<unsigned char*>(data); }); + return pBlob; +} + +hb_font_t* CoreTextStyle::ImplInitHbFont() +{ + // On macOS we use HarfBuzz for AAT shaping, but HarfBuzz will then + // need a CGFont (as it offloads the actual AAT shaping to Core Text), + // if we have one we use it to create the hb_face_t. + hb_face_t* pHbFace; + CTFontRef pCTFont = static_cast<CTFontRef>(CFDictionaryGetValue(GetStyleDict(), kCTFontAttributeName)); + CGFontRef pCGFont = CTFontCopyGraphicsFont(pCTFont, nullptr); + if (pCGFont) + pHbFace = hb_coretext_face_create(pCGFont); + else + pHbFace = hb_face_create_for_tables(getFontTable, const_cast<PhysicalFontFace*>(GetFontFace()), nullptr); + CGFontRelease(pCGFont); + + return InitHbFont(pHbFace); +} + PhysicalFontFace* CoreTextFontFace::Clone() const { return new CoreTextFontFace( *this); @@ -277,6 +310,11 @@ int CoreTextFontFace::GetFontTable( const char pTagName[5], unsigned char* pResu const CTFontTableTag nTagCode = (pTagName[0]<<24) + (pTagName[1]<<16) + (pTagName[2]<<8) + (pTagName[3]<<0); + return GetFontTable(nTagCode, pResultBuf); +} + +int CoreTextFontFace::GetFontTable(uint32_t nTagCode, unsigned char* pResultBuf ) const +{ // get the raw table length CTFontDescriptorRef pFontDesc = reinterpret_cast<CTFontDescriptorRef>( GetFontId()); CTFontRef rCTFont = CTFontCreateWithFontDescriptor( pFontDesc, 0.0, nullptr); diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx index 80825e77c84f..9e8d8df100a4 100644 --- a/vcl/quartz/salgdi.cxx +++ b/vcl/quartz/salgdi.cxx @@ -409,7 +409,7 @@ bool AquaSalGraphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangl void AquaSalGraphics::DrawTextLayout(const CommonSalLayout& rLayout) { - const CoreTextStyle& rStyle = rLayout.getFontData(); + const CoreTextStyle& rStyle = *static_cast<const CoreTextStyle*>(&rLayout.getFont()); const FontSelectPattern& rFontSelect = rStyle.GetFontSelectPattern(); if (rFontSelect.mnHeight == 0) return; diff --git a/vcl/source/font/fontcache.cxx b/vcl/source/font/fontcache.cxx index 1aa5f3e4c700..3e4945505144 100644 --- a/vcl/source/font/fontcache.cxx +++ b/vcl/source/font/fontcache.cxx @@ -20,6 +20,7 @@ #include <svdata.hxx> #include <fontinstance.hxx> +#include <impfontcache.hxx> #include <PhysicalFontCollection.hxx> #include <PhysicalFontFace.hxx> #include <PhysicalFontFamily.hxx> diff --git a/vcl/source/font/fontinstance.cxx b/vcl/source/font/fontinstance.cxx index 5f9ac49afcf7..845eb2e9e635 100644 --- a/vcl/source/font/fontinstance.cxx +++ b/vcl/source/font/fontinstance.cxx @@ -20,6 +20,9 @@ #include <svdata.hxx> #include <fontinstance.hxx> +#include <impfontcache.hxx> + +#include <PhysicalFontFace.hxx> // extend std namespace to add custom hash needed for LogicalFontInstance @@ -47,6 +50,8 @@ LogicalFontInstance::LogicalFontInstance(const PhysicalFontFace& rFontFace, cons , mpFontCache( nullptr ) , mnRefCount( 1 ) , m_aFontSelData(rFontSelData) + , m_pHbFont(nullptr) + , m_nAveWidthFactor(1.0f) , m_pFontFace(&rFontFace) { const_cast<FontSelectPattern*>(&m_aFontSelData)->mpFontInstance = this; @@ -57,6 +62,41 @@ LogicalFontInstance::~LogicalFontInstance() mpUnicodeFallbackList.reset(); mpFontCache = nullptr; mxFontMetric = nullptr; + + if (m_pHbFont) + hb_font_destroy(m_pHbFont); +} + +hb_font_t* LogicalFontInstance::InitHbFont(hb_face_t* pHbFace) const +{ + assert(pHbFace); + hb_font_t* pHbFont = hb_font_create(pHbFace); + unsigned int nUPEM = hb_face_get_upem(pHbFace); + hb_font_set_scale(pHbFont, nUPEM, nUPEM); + hb_ot_font_set_funcs(pHbFont); + // hb_font_t keeps a reference to hb_face_t, so destroy this one. + hb_face_destroy(pHbFace); + return pHbFont; +} + +void LogicalFontInstance::GetScale(double* nXScale, double* nYScale) +{ + hb_face_t* pHbFace = hb_font_get_face(GetHbFont()); + unsigned int nUPEM = hb_face_get_upem(pHbFace); + + double nHeight(m_aFontSelData.mnHeight); + + // On Windows, mnWidth is relative to average char width not font height, + // and we need to keep it that way for GDI to correctly scale the glyphs. + // Here we compensate for this so that HarfBuzz gives us the correct glyph + // positions. + double nWidth(m_aFontSelData.mnWidth ? m_aFontSelData.mnWidth * m_nAveWidthFactor : nHeight); + + if (nYScale) + *nYScale = nHeight / nUPEM; + + if (nXScale) + *nXScale = nWidth / nUPEM; } void LogicalFontInstance::Acquire() diff --git a/vcl/source/font/fontselect.cxx b/vcl/source/font/fontselect.cxx index fd67335eb1cd..80b9ba78ce6b 100644 --- a/vcl/source/font/fontselect.cxx +++ b/vcl/source/font/fontselect.cxx @@ -20,6 +20,8 @@ #include <sal/config.h> #include <o3tl/safeint.hxx> +#include <fontselect.hxx> + #include <PhysicalFontFace.hxx> #include <svdata.hxx> diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx index 120993557634..0cc0c06c382c 100644 --- a/vcl/source/gdi/CommonSalLayout.cxx +++ b/vcl/source/gdi/CommonSalLayout.cxx @@ -29,119 +29,8 @@ #include <salgdi.hxx> #include <unicode/uchar.h> -#if ENABLE_QT5 -#include <qt5/Qt5Font.hxx> -#include <QtGui/QRawFont> -#endif - -static inline void decode_hb_tag( const hb_tag_t nTableTag, char *pTagName ) -{ - pTagName[0] = static_cast<char>(nTableTag >> 24); - pTagName[1] = static_cast<char>(nTableTag >> 16); - pTagName[2] = static_cast<char>(nTableTag >> 8); - pTagName[3] = static_cast<char>(nTableTag); - pTagName[4] = 0; -} - -static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) -{ - char pTagName[5]; - decode_hb_tag( nTableTag, pTagName ); - - sal_uLong nLength = 0; -#if defined(_WIN32) - unsigned char* pBuffer = nullptr; - HFONT hFont = static_cast<HFONT>(pUserData); - HDC hDC = GetDC(nullptr); - HGDIOBJ hOrigFont = SelectObject(hDC, hFont); - nLength = ::GetFontData(hDC, OSL_NETDWORD(nTableTag), 0, nullptr, 0); - if (nLength > 0 && nLength != GDI_ERROR) - { - pBuffer = new unsigned char[nLength]; - ::GetFontData(hDC, OSL_NETDWORD(nTableTag), 0, pBuffer, nLength); - } - SelectObject(hDC, hOrigFont); - ReleaseDC(nullptr, hDC); -#elif defined(MACOSX) || defined(IOS) - unsigned char* pBuffer = nullptr; - CoreTextFontFace* pFont = static_cast<CoreTextFontFace*>(pUserData); - nLength = pFont->GetFontTable(pTagName, nullptr); - if (nLength > 0) - { - pBuffer = new unsigned char[nLength]; - pFont->GetFontTable(pTagName, pBuffer); - } -#else - FreetypeFont* pFont = static_cast<FreetypeFont*>( pUserData ); - const char* pBuffer = reinterpret_cast<const char*>( - pFont->GetTable(pTagName, &nLength) ); -#endif - - hb_blob_t* pBlob = nullptr; - if (pBuffer != nullptr) -#if defined(_WIN32) || defined(MACOSX) || defined(IOS) - pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY, - pBuffer, [](void* data){ delete[] static_cast<unsigned char*>(data); }); -#else - pBlob = hb_blob_create(pBuffer, nLength, HB_MEMORY_MODE_READONLY, nullptr, nullptr); -#endif - - return pBlob; -} - -#if ENABLE_QT5 -static hb_blob_t* getFontTable_Qt5Font(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) -{ - char pTagName[5]; - decode_hb_tag( nTableTag, pTagName ); - - Qt5Font *pFont = static_cast<Qt5Font*>( pUserData ); - QRawFont aRawFont( QRawFont::fromFont( *pFont ) ); - QByteArray aTable = aRawFont.fontTable( pTagName ); - const sal_uLong nLength = aTable.size(); - - hb_blob_t* pBlob = nullptr; - if (nLength > 0) - pBlob = hb_blob_create(reinterpret_cast<const char*>( aTable.data() ), - nLength, HB_MEMORY_MODE_READONLY, nullptr, nullptr); - return pBlob; -} -#endif - -static hb_font_t* createHbFont(hb_face_t* pHbFace) -{ - hb_font_t* pHbFont = hb_font_create(pHbFace); - unsigned int nUPEM = hb_face_get_upem(pHbFace); - hb_font_set_scale(pHbFont, nUPEM, nUPEM); - hb_ot_font_set_funcs(pHbFont); - - hb_face_destroy(pHbFace); - - return pHbFont; -} - -void CommonSalLayout::getScale(double* nXScale, double* nYScale) -{ - hb_face_t* pHbFace = hb_font_get_face(mpHbFont); - unsigned int nUPEM = hb_face_get_upem(pHbFace); - - double nHeight(mrFontSelData.mnHeight); -#if defined(_WIN32) - // On Windows, mnWidth is relative to average char width not font height, - // and we need to keep it that way for GDI to correctly scale the glyphs. - // Here we compensate for this so that HarfBuzz gives us the correct glyph - // positions. - double nWidth(mrFontSelData.mnWidth ? mrFontSelData.mnWidth * mnAveWidthFactor : nHeight); -#else - double nWidth(mrFontSelData.mnWidth ? mrFontSelData.mnWidth : nHeight); -#endif - - if (nYScale) - *nYScale = nHeight / nUPEM; - - if (nXScale) - *nXScale = nWidth / nUPEM; -} +#include <fontselect.hxx> +#include <impfontcache.hxx> #if !HB_VERSION_ATLEAST(1, 1, 0) // Disabled Unicode compatibility decomposition, see fdo#66715 @@ -161,6 +50,19 @@ static hb_unicode_funcs_t* getUnicodeFuncs() } #endif +CommonSalLayout::CommonSalLayout(LogicalFontInstance &rFont) + : mpFont(&rFont) + , mpVertGlyphs(nullptr) + , mbFuzzing(utl::ConfigManager::IsFuzzing()) +{ + mpFont->Acquire(); +} + +CommonSalLayout::~CommonSalLayout() +{ + mpFont->Release(); +} + void CommonSalLayout::ParseFeatures(const OUString& aName) { if (aName.indexOf(FontSelectPatternAttributes::FEAT_PREFIX) < 0) @@ -186,159 +88,8 @@ void CommonSalLayout::ParseFeatures(const OUString& aName) while (nIndex >= 0); } -#if defined(_WIN32) -CommonSalLayout::CommonSalLayout(HDC hDC, WinFontInstance& rWinFontInstance) -: mrFontSelData(rWinFontInstance.GetFontSelectPattern()) -, mhDC(hDC) -, mhFont(static_cast<HFONT>(GetCurrentObject(hDC, OBJ_FONT))) -, mrWinFontInstance(rWinFontInstance) -, mnAveWidthFactor(1.0f) -, mpVertGlyphs(nullptr) -, mbFuzzing(utl::ConfigManager::IsFuzzing()) -{ - const WinFontFace& rWinFontFace = *static_cast<const WinFontFace*>(rWinFontInstance.GetFontFace()); - mpHbFont = rWinFontFace.GetHbFont(); - if (!mpHbFont) - { - hb_face_t* pHbFace = hb_face_create_for_tables(getFontTable, mhFont, nullptr); - - mpHbFont = createHbFont(pHbFace); - rWinFontFace.SetHbFont(mpHbFont); - } - - // Calculate the mnAveWidthFactor, see the comment where it is used. - if (mrFontSelData.mnWidth) - { - double nUPEM = hb_face_get_upem(hb_font_get_face(mpHbFont)); - - LOGFONTW aLogFont; - GetObjectW(mhFont, sizeof(LOGFONTW), &aLogFont); - - // Set the height (font size) to EM to minimize rounding errors. - aLogFont.lfHeight = -nUPEM; - // Set width to the default to get the original value in the metrics. - aLogFont.lfWidth = 0; - - // Get the font metrics. - HFONT hNewFont = CreateFontIndirectW(&aLogFont); - HFONT hOldFont = static_cast<HFONT>(SelectObject(hDC, hNewFont)); - TEXTMETRICW aFontMetric; - GetTextMetricsW(hDC, &aFontMetric); - SelectObject(hDC, hOldFont); - DeleteObject(hNewFont); - - mnAveWidthFactor = nUPEM / aFontMetric.tmAveCharWidth; - } -} - -bool CommonSalLayout::hasHScale() const -{ - int nHeight(mrFontSelData.mnHeight); - int nWidth(mrFontSelData.mnWidth ? mrFontSelData.mnWidth * mnAveWidthFactor : nHeight); - return nWidth != nHeight; -} - -#elif defined(MACOSX) || defined(IOS) -CommonSalLayout::CommonSalLayout(const CoreTextStyle& rCoreTextStyle) -: mrFontSelData(rCoreTextStyle.GetFontSelectPattern()) -, mrCoreTextStyle(rCoreTextStyle) -, mpVertGlyphs(nullptr) -, mbFuzzing(utl::ConfigManager::IsFuzzing()) -{ - mpHbFont = rCoreTextStyle.GetHbFont(); - if (!mpHbFont) - { - // On macOS we use HarfBuzz for AAT shaping, but HarfBuzz will then - // need a CGFont (as it offloads the actual AAT shaping to Core Text), - // if we have one we use it to create the hb_face_t. - hb_face_t* pHbFace; - CTFontRef pCTFont = static_cast<CTFontRef>(CFDictionaryGetValue(rCoreTextStyle.GetStyleDict(), kCTFontAttributeName)); - CGFontRef pCGFont = CTFontCopyGraphicsFont(pCTFont, nullptr); - if (pCGFont) - pHbFace = hb_coretext_face_create(pCGFont); - else - pHbFace = hb_face_create_for_tables(getFontTable, const_cast<PhysicalFontFace*>(rCoreTextStyle.GetFontFace()), nullptr); - CGFontRelease(pCGFont); - - mpHbFont = createHbFont(pHbFace); - rCoreTextStyle.SetHbFont(mpHbFont); - } -} - -#else - -void CommonSalLayout::InitFromFreetypeFont() -{ - mpHbFont = mpFreetypeFont->GetHbFont(); - if (!mpHbFont) - { - hb_face_t* pHbFace = hb_face_create_for_tables(getFontTable, mpFreetypeFont, nullptr); - mpHbFont = createHbFont(pHbFace); - mpFreetypeFont->SetHbFont(mpHbFont); - } -} - -#if ENABLE_QT5 -CommonSalLayout::CommonSalLayout(const FontSelectPattern &rFSP, - FreetypeFont *pFreetypeFont, - Qt5Font *pQt5Font, bool bUseQt5) - : mrFontSelData(rFSP) - , mpFreetypeFont(pFreetypeFont) - , mbUseQt5(bUseQt5) - , mpQFont(pQt5Font) - , mpVertGlyphs(nullptr) - , mbFuzzing(utl::ConfigManager::IsFuzzing()) -{ - if (mbUseQt5) - { - assert( pQt5Font && !pFreetypeFont ); - mpHbFont = mpQFont->GetHbFont(); - if (!mpHbFont) - { - hb_face_t* pHbFace = hb_face_create_for_tables( - getFontTable_Qt5Font, pQt5Font, nullptr); - mpHbFont = createHbFont(pHbFace); - mpQFont->SetHbFont(mpHbFont); - } - } - else - { - assert( !pQt5Font && pFreetypeFont ); - InitFromFreetypeFont(); - } -} - -CommonSalLayout::CommonSalLayout(FreetypeFont& rFreetypeFont) - : CommonSalLayout(rFreetypeFont.GetFontSelData(), - &rFreetypeFont, nullptr, false) -{ -} - -CommonSalLayout::CommonSalLayout(Qt5Font& rQFont) - : CommonSalLayout(rQFont.GetFontSelectPattern(), - nullptr, &rQFont, true) -{ -} - -#else // ! ENABLE_QT5 - -CommonSalLayout::CommonSalLayout(FreetypeFont& rFreetypeFont) - : mrFontSelData(rFreetypeFont.GetFontSelData()) - , mpFreetypeFont(&rFreetypeFont) - , mpVertGlyphs(nullptr) - , mbFuzzing(utl::ConfigManager::IsFuzzing()) -{ - InitFromFreetypeFont(); -} - -#endif -#endif - void CommonSalLayout::InitFont() const { -#if defined(_WIN32) - SelectObject(mhDC, mhFont); -#endif } struct SubRun @@ -484,12 +235,13 @@ void CommonSalLayout::DrawText(SalGraphics& rSalGraphics) const bool CommonSalLayout::HasVerticalAlternate(sal_UCS4 aChar, sal_UCS4 aVariationSelector) { hb_codepoint_t nGlyphIndex = 0; - if (!hb_font_get_glyph(mpHbFont, aChar, aVariationSelector, &nGlyphIndex)) + hb_font_t *pHbFont = mpFont->GetHbFont(); + if (!hb_font_get_glyph(pHbFont, aChar, aVariationSelector, &nGlyphIndex)) return false; if (!mpVertGlyphs) { - hb_face_t* pHbFace = hb_font_get_face(mpHbFont); + hb_face_t* pHbFace = hb_font_get_face(pHbFont); mpVertGlyphs = hb_set_create(); // Find all GSUB lookups for “vert” feature. @@ -519,7 +271,8 @@ bool CommonSalLayout::HasVerticalAlternate(sal_UCS4 aChar, sal_UCS4 aVariationSe bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs) { - hb_face_t* pHbFace = hb_font_get_face(mpHbFont); + hb_font_t *pHbFont = mpFont->GetHbFont(); + hb_face_t* pHbFace = hb_font_get_face(pHbFont); int nGlyphCapacity = 2 * (rArgs.mnEndCharPos - rArgs.mnMinCharPos); Reserve(nGlyphCapacity); @@ -546,17 +299,18 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs) hb_buffer_set_unicode_funcs(pHbBuffer, pHbUnicodeFuncs); #endif + const FontSelectPattern& rFontSelData = mpFont->GetFontSelectPattern(); if (rArgs.mnFlags & SalLayoutFlags::DisableKerning) { - SAL_INFO("vcl.harfbuzz", "Disabling kerning for font: " << mrFontSelData.maTargetName); + SAL_INFO("vcl.harfbuzz", "Disabling kerning for font: " << rFontSelData.maTargetName); maFeatures.push_back({ HB_TAG('k','e','r','n'), 0, 0, static_cast<unsigned int>(-1) }); } - ParseFeatures(mrFontSelData.maTargetName); + ParseFeatures(rFontSelData.maTargetName); double nXScale = 0; double nYScale = 0; - getScale(&nXScale, &nYScale); + mpFont->GetScale(&nXScale, &nYScale); Point aCurrPos(0, 0); while (true) @@ -682,7 +436,7 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs) hb_segment_properties_t aHbProps; hb_buffer_get_segment_properties(pHbBuffer, &aHbProps); hb_shape_plan_t* pHbPlan = hb_shape_plan_create_cached(pHbFace, &aHbProps, maFeatures.data(), maFeatures.size(), pHbShapers); - bool ok = hb_shape_plan_execute(pHbPlan, mpHbFont, pHbBuffer, maFeatures.data(), maFeatures.size()); + bool ok = hb_shape_plan_execute(pHbPlan, pHbFont, pHbBuffer, maFeatures.data(), maFeatures.size()); assert(ok); (void) ok; hb_buffer_set_content_type(pHbBuffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); @@ -795,7 +549,7 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs) // We have glyph offsets that is relative to h origin now, // add the origin back so it is relative to v origin. - hb_font_add_glyph_origin_for_direction( mpHbFont, + hb_font_add_glyph_origin_for_direction(pHbFont, nGlyphIndex, HB_DIRECTION_TTB, &pHbPositions[i].x_offset , @@ -887,12 +641,13 @@ void CommonSalLayout::ApplyDXArray(ImplLayoutArgs& rArgs) hb_codepoint_t nKashidaIndex = 0; if (rArgs.mnFlags & SalLayoutFlags::KashidaJustification) { + hb_font_t *pHbFont = mpFont->GetHbFont(); // Find Kashida glyph width and index. - if (hb_font_get_glyph(mpHbFont, 0x0640, 0, &nKashidaIndex)) + if (hb_font_get_glyph(pHbFont, 0x0640, 0, &nKashidaIndex)) { double nXScale = 0; - getScale(&nXScale, nullptr); - nKashidaWidth = hb_font_get_glyph_h_advance(mpHbFont, nKashidaIndex) * nXScale; + mpFont->GetScale(&nXScale, nullptr); + nKashidaWidth = hb_font_get_glyph_h_advance(pHbFont, nKashidaIndex) * nXScale; } bKashidaJustify = nKashidaWidth != 0; } diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 879834c0da4c..24a562925ff3 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -1756,7 +1756,7 @@ void Window::ImplNewInputContext() pFontInstance = pFocusWin->mpFontCache->GetFontInstance( pFocusWin->mpFontCollection, rFont, aSize, static_cast<float>(aSize.Height()) ); if ( pFontInstance ) - aNewContext.mpFont = &pFontInstance->GetFontSelectPattern(); + aNewContext.mpFont = pFontInstance; } aNewContext.meLanguage = rFont.GetLanguage(); aNewContext.mnOptions = rInputContext.GetOptions(); diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx index bde9ff6827ac..d856821de72c 100644 --- a/vcl/unx/generic/gdi/cairotextrender.cxx +++ b/vcl/unx/generic/gdi/cairotextrender.cxx @@ -31,6 +31,7 @@ #include <unx/geninst.h> #include <unx/glyphcache.hxx> #include <unx/fc_fontoptions.hxx> +#include <unx/freetype_glyphcache.hxx> #include <PhysicalFontFace.hxx> #include <impfont.hxx> #include <impfontmetricdata.hxx> @@ -169,7 +170,8 @@ namespace void CairoTextRender::DrawTextLayout(const CommonSalLayout& rLayout) { - const FreetypeFont& rFont = *rLayout.getFreetypeFont(); + const FreetypeFontInstance& rInstance = static_cast<FreetypeFontInstance&>(rLayout.getFont()); + const FreetypeFont& rFont = *rInstance.GetFreetypeFont(); std::vector<cairo_glyph_t> cairo_glyphs; std::vector<int> glyph_extrarotation; @@ -195,7 +197,7 @@ void CairoTextRender::DrawTextLayout(const CommonSalLayout& rLayout) if (cairo_glyphs.empty()) return; - const FontSelectPattern& rFSD = rFont.GetFontSelData(); + const FontSelectPattern& rFSD = rInstance.GetFontSelectPattern(); int nHeight = rFSD.mnHeight; int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight; if (nWidth == 0 || nHeight == 0) @@ -460,7 +462,7 @@ bool CairoTextRender::GetGlyphOutline(const GlyphItem& rGlyph, if( nLevel >= MAX_FALLBACK ) return false; - FreetypeFont* pSF = mpFreetypeFont[ nLevel ]; + const FreetypeFont* pSF = mpFreetypeFont[ nLevel ]; if( !pSF ) return false; @@ -470,7 +472,7 @@ bool CairoTextRender::GetGlyphOutline(const GlyphItem& rGlyph, std::unique_ptr<SalLayout> CairoTextRender::GetTextLayout(ImplLayoutArgs& /*rArgs*/, int nFallbackLevel) { if (mpFreetypeFont[nFallbackLevel]) - return std::unique_ptr<SalLayout>(new CommonSalLayout(*mpFreetypeFont[nFallbackLevel])); + return std::unique_ptr<SalLayout>(new CommonSalLayout(*mpFreetypeFont[nFallbackLevel]->GetFontInstance())); return nullptr; } @@ -485,13 +487,13 @@ SystemFontData CairoTextRender::GetSysFontData( int nFallbackLevel ) const if (mpFreetypeFont[nFallbackLevel] != nullptr) { - FreetypeFont* rFont = mpFreetypeFont[nFallbackLevel]; + const FreetypeFont* rFont = mpFreetypeFont[nFallbackLevel]; aSysFontData.nFontId = rFont->GetFtFace(); aSysFontData.nFontFlags = rFont->GetLoadFlags(); aSysFontData.bFakeBold = rFont->NeedsArtificialBold(); aSysFontData.bFakeItalic = rFont->NeedsArtificialItalic(); aSysFontData.bAntialias = rFont->GetAntialiasAdvice(); - aSysFontData.bVerticalCharacterType = rFont->GetFontSelData().mbVertical; + aSysFontData.bVerticalCharacterType = rFont->GetFontInstance()->GetFontSelectPattern().mbVertical; } return aSysFontData; @@ -555,4 +557,5 @@ void CairoTextRender::GetGlyphWidths( const PhysicalFontFace* pFont, psp::fontID aFont = pFont->GetFontId(); GenPspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc ); } + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx index 795284493f12..b2b1c59f67cf 100644 --- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx +++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx @@ -367,7 +367,7 @@ LogicalFontInstance* FreetypeFontFace::CreateFontInstance(const FontSelectPatter FreetypeFont::FreetypeFont( const FontSelectPattern& rFSD, FreetypeFontInfo* pFI ) : maGlyphList( 0), - maFontSelData(rFSD), + mpFontInstance(rFSD.mpFontInstance), mnRefCount(1), mnBytesUsed( sizeof(FreetypeFont) ), mpPrevGCFont( nullptr ), @@ -382,13 +382,12 @@ FreetypeFont::FreetypeFont( const FontSelectPattern& rFSD, FreetypeFontInfo* pFI maSizeFT( nullptr ), mbFaceOk( false ), mbArtItalic( false ), - mbArtBold( false ), - mpHbFont( nullptr ) + mbArtBold(false) { // TODO: move update of mpFontInstance into FontEntry class when // it becomes responsible for the FreetypeFont instantiation - static_cast<FreetypeFontInstance*>(rFSD.mpFontInstance)->SetFreetypeFont( this ); - maFontSelData.mpFontInstance->Acquire(); + static_cast<FreetypeFontInstance*>(mpFontInstance)->SetFreetypeFont( this ); + mpFontInstance->Acquire(); maFaceFT = pFI->GetFaceFT(); @@ -459,7 +458,7 @@ const FontConfigFontOptions* FreetypeFont::GetFontOptions() const { if (!mxFontOptions) { - mxFontOptions.reset(GetFCFontOptions(mpFontInfo->GetFontAttributes(), maFontSelData.mnHeight)); + mxFontOptions.reset(GetFCFontOptions(mpFontInfo->GetFontAttributes(), mpFontInstance->GetFontSelectPattern().mnHeight)); mxFontOptions->SyncPattern(GetFontFileName(), GetFontFaceIndex(), NeedsArtificialBold()); } return mxFontOptions.get(); @@ -487,10 +486,7 @@ FreetypeFont::~FreetypeFont() mpFontInfo->ReleaseFaceFT(); - if( mpHbFont ) - hb_font_destroy( mpHbFont ); - - maFontSelData.mpFontInstance->Release(); + mpFontInstance->Release(); ReleaseFromGarbageCollect(); } @@ -499,7 +495,7 @@ void FreetypeFont::GetFontMetric(ImplFontMetricDataRef const & rxTo) const { rxTo->FontAttributes::operator =(mpFontInfo->GetFontAttributes()); - rxTo->SetOrientation( maFontSelData.mnOrientation ); + rxTo->SetOrientation( mpFontInstance->GetFontSelectPattern().mnOrientation ); //Always consider [star]symbol as symbol fonts if ( IsStarSymbol( rxTo->GetFamilyName() ) ) @@ -569,7 +565,7 @@ void FreetypeFont::GetFontMetric(ImplFontMetricDataRef const & rxTo) const void FreetypeFont::ApplyGlyphTransform(bool bVertical, FT_Glyph pGlyphFT ) const { // shortcut most common case - if (!maFontSelData.mnOrientation && !bVertical) + if (!mpFontInstance->GetFontSelectPattern().mnOrientation && !bVertical) return; const FT_Size_Metrics& rMetrics = maFaceFT->size->metrics; @@ -650,7 +646,7 @@ void FreetypeFont::InitGlyphData(const GlyphItem& rGlyph, GlyphData& rGD ) const bool FreetypeFont::GetAntialiasAdvice() const { // TODO: also use GASP info - return !maFontSelData.mbNonAntialiased && (mnPrioAntiAlias > 0); + return !mpFontInstance->GetFontSelectPattern().mbNonAntialiased && (mnPrioAntiAlias > 0); } // determine unicode ranges in font diff --git a/vcl/unx/generic/glyphs/glyphcache.cxx b/vcl/unx/generic/glyphs/glyphcache.cxx index ac2f8cf83218..218161c65be2 100644 --- a/vcl/unx/generic/glyphs/glyphcache.cxx +++ b/vcl/unx/generic/glyphs/glyphcache.cxx @@ -259,7 +259,7 @@ void GlyphCache::GarbageCollect() pFreetypeFont->GarbageCollect( mnLruIndex+0x10000000 ); if( pFreetypeFont == mpCurrentGCFont ) mpCurrentGCFont = nullptr; - const FontSelectPattern& rIFSD = pFreetypeFont->GetFontSelData(); + const FontSelectPattern& rIFSD = pFreetypeFont->GetFontInstance()->GetFontSelectPattern(); maFontList.erase( rIFSD ); mnBytesUsed -= pFreetypeFont->GetByteCount(); @@ -370,4 +370,28 @@ FreetypeFontInstance::~FreetypeFontInstance() if (mpFreetypeFont) mpFreetypeFont->Release(); } + +static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) +{ + char pTagName[5]; + LogicalFontInstance::DecodeOpenTypeTag( nTableTag, pTagName ); + + sal_uLong nLength = 0; + FreetypeFontInstance* pFontInstance = static_cast<FreetypeFontInstance*>( pUserData ); + FreetypeFont* pFont = pFontInstance->GetFreetypeFont(); + const char* pBuffer = reinterpret_cast<const char*>( + pFont->GetTable(pTagName, &nLength) ); + + hb_blob_t* pBlob = nullptr; + if (pBuffer != nullptr) + pBlob = hb_blob_create(pBuffer, nLength, HB_MEMORY_MODE_READONLY, nullptr, nullptr); + + return pBlob; +} + +hb_font_t* FreetypeFontInstance::ImplInitHbFont() +{ + return InitHbFont(hb_face_create_for_tables(getFontTable, this, nullptr)); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx index d651da2812c6..c1f1caf014a0 100644 --- a/vcl/unx/generic/print/genpspgraphics.cxx +++ b/vcl/unx/generic/print/genpspgraphics.cxx @@ -547,7 +547,7 @@ private: }; PspCommonSalLayout::PspCommonSalLayout(::psp::PrinterGfx& rGfx, FreetypeFont& rFont) -: CommonSalLayout(rFont) +: CommonSalLayout(*rFont.GetFontInstance()) , mrPrinterGfx(rGfx) { mnFontID = mrPrinterGfx.GetFontID(); diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx index 2c96edc91fbe..62d9f7d85dd7 100644 --- a/vcl/win/gdi/salfont.cxx +++ b/vcl/win/gdi/salfont.cxx @@ -622,8 +622,7 @@ WinFontFace::WinFontFace( const FontAttributes& rDFS, meWinCharSet( eWinCharSet ), mnPitchAndFamily( nPitchAndFamily ), mbAliasSymbolsHigh( false ), - mbAliasSymbolsLow( false ), - mpHbFont( nullptr ) + mbAliasSymbolsLow( false ) { SetBitmapSize( 0, nHeight ); @@ -652,9 +651,6 @@ WinFontFace::WinFontFace( const FontAttributes& rDFS, WinFontFace::~WinFontFace() { mxUnicodeMap.clear(); - - if( mpHbFont ) - hb_font_destroy( mpHbFont ); } sal_IntPtr WinFontFace::GetFontId() const @@ -662,6 +658,16 @@ sal_IntPtr WinFontFace::GetFontId() const return mnId; } +PhysicalFontFace* WinFontFace::Clone() const +{ + return new WinFontFace(*this); +} + +LogicalFontInstance* WinFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const +{ + return new WinFontInstance(*this, rFSD); +} + static inline DWORD CalcTag( const char p[5]) { return (p[0]+(p[1]<<8)+(p[2]<<16)+(p[3]<<24)); } void WinFontFace::UpdateFromHDC( HDC hDC ) const diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx index cc37b866848d..3188f7f3d0bb 100644 --- a/vcl/win/gdi/winlayout.cxx +++ b/vcl/win/gdi/winlayout.cxx @@ -251,7 +251,7 @@ bool ExTextOutRenderer::operator ()(CommonSalLayout const &rLayout, HFONT hAltFont = nullptr; bool bUseAltFont = false; bool bShift = false; - if (rLayout.getFontSelData().mbVertical) + if (rLayout.getFont().GetFontSelectPattern().mbVertical) { LOGFONTW aLogFont; GetObjectW(hFont, sizeof(aLogFont), &aLogFont); @@ -307,7 +307,9 @@ std::unique_ptr<SalLayout> WinSalGraphics::GetTextLayout(ImplLayoutArgs& /*rArgs assert(mpWinFontEntry[nFallbackLevel]->GetFontFace()); - return std::unique_ptr<SalLayout>(new CommonSalLayout(getHDC(), *mpWinFontEntry[nFallbackLevel])); + mpWinFontEntry[nFallbackLevel]->SetHDC(getHDC()); + CommonSalLayout *aLayout = new CommonSalLayout(*mpWinFontEntry[nFallbackLevel]); + return std::unique_ptr<SalLayout>(aLayout); } LogicalFontInstance * WinSalGraphics::GetWinFontEntry(int const nFallbackLevel) @@ -324,18 +326,76 @@ WinFontInstance::~WinFontInstance() { } -PhysicalFontFace* WinFontFace::Clone() const +bool WinFontInstance::hasHScale() const { - if( mpHbFont ) - hb_font_reference( mpHbFont ); + const FontSelectPattern &rPattern = GetFontSelectPattern(); + int nHeight(rPattern.mnHeight); + int nWidth(rPattern.mnWidth ? rPattern.mnWidth * GetAverageWidthFactor() : nHeight); + return nWidth != nHeight; +} - PhysicalFontFace* pClone = new WinFontFace( *this ); - return pClone; +static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) +{ + sal_uLong nLength = 0; + unsigned char* pBuffer = nullptr; + HFONT hFont = static_cast<HFONT>(pUserData); + HDC hDC = GetDC(nullptr); + HGDIOBJ hOrigFont = SelectObject(hDC, hFont); + nLength = ::GetFontData(hDC, OSL_NETDWORD(nTableTag), 0, nullptr, 0); + if (nLength > 0 && nLength != GDI_ERROR) + { + pBuffer = new unsigned char[nLength]; + ::GetFontData(hDC, OSL_NETDWORD(nTableTag), 0, pBuffer, nLength); + } + SelectObject(hDC, hOrigFont); + ReleaseDC(nullptr, hDC); + + hb_blob_t* pBlob = nullptr; + if (pBuffer != nullptr) + pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY, + pBuffer, [](void* data){ delete[] static_cast<unsigned char*>(data); }); + return pBlob; } -LogicalFontInstance* WinFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const +hb_font_t* WinFontInstance::ImplInitHbFont() { - return new WinFontInstance(*this, rFSD); + assert(m_hDC); + m_hFont = static_cast<HFONT>(GetCurrentObject(m_hDC, OBJ_FONT)); + hb_font_t* pHbFont = InitHbFont(hb_face_create_for_tables(getFontTable, m_hFont, nullptr)); + + // Calculate the AverageWidthFactor, see LogicalFontInstance::GetScale(). + if (GetFontSelectPattern().mnWidth) + { + double nUPEM = hb_face_get_upem(hb_font_get_face(pHbFont)); + + LOGFONTW aLogFont; + GetObjectW(m_hFont, sizeof(LOGFONTW), &aLogFont); + + // Set the height (font size) to EM to minimize rounding errors. + aLogFont.lfHeight = -nUPEM; + // Set width to the default to get the original value in the metrics. + aLogFont.lfWidth = 0; + + // Get the font metrics. + HFONT hNewFont = CreateFontIndirectW(&aLogFont); + HFONT hOldFont = static_cast<HFONT>(SelectObject(m_hDC, hNewFont)); + TEXTMETRICW aFontMetric; + GetTextMetricsW(m_hDC, &aFontMetric); + SelectObject(m_hDC, hOldFont); + DeleteObject(hNewFont); + + SetAverageWidthFactor(nUPEM / aFontMetric.tmAveCharWidth); + } + + return pHbFont; +} + +void WinFontInstance::SetHDC(const HDC hDC) +{ + if (m_hDC == hDC) + return; + ReleaseHbFont(); + m_hDC = hDC; } bool WinSalGraphics::CacheGlyphs(const CommonSalLayout& rLayout) @@ -345,8 +405,8 @@ bool WinSalGraphics::CacheGlyphs(const CommonSalLayout& rLayout) return false; HDC hDC = getHDC(); - HFONT hFONT = rLayout.getHFONT(); - WinFontInstance& rFont = rLayout.getWinFontInstance(); + WinFontInstance& rFont = *static_cast<WinFontInstance*>(&rLayout.getFont()); + HFONT hFONT = rFont.GetHFONT(); int nStart = 0; Point aPos(0, 0); @@ -377,7 +437,7 @@ bool WinSalGraphics::DrawCachedGlyphs(const CommonSalLayout& rLayout) if (!pImpl) return false; - WinFontInstance& rFont = rLayout.getWinFontInstance(); + WinFontInstance& rFont = *static_cast<WinFontInstance*>(&rLayout.getFont()); int nStart = 0; Point aPos(0, 0); @@ -412,9 +472,12 @@ void WinSalGraphics::DrawTextLayout(const CommonSalLayout& rLayout) { HDC hDC = getHDC(); + HFONT hFont = static_cast<const WinFontInstance*>(&rLayout.getFont())->GetHFONT(); + HGDIOBJ hOrigFont = SelectObject(hDC, hFont); + // Our DirectWrite renderer is incomplete, skip it for non-horizontal or // stretched text. - bool bForceGDI = rLayout.GetOrientation() || rLayout.hasHScale(); + bool bForceGDI = rLayout.GetOrientation() || static_cast<const WinFontInstance*>(&rLayout.getFont())->hasHScale(); bool bUseOpenGL = OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter; if (!bUseOpenGL) @@ -477,7 +540,7 @@ void WinSalGraphics::DrawTextLayout(const CommonSalLayout& rLayout) // setup the hidden DC with black color and white background, we will // use the result of the text drawing later as a mask only - HFONT hOrigFont = ::SelectFont(aDC.getCompatibleHDC(), static_cast<HFONT>(::GetCurrentObject(hDC, OBJ_FONT))); + HFONT hOFont = ::SelectFont(aDC.getCompatibleHDC(), hFont); ::SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0)); ::SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255)); @@ -495,11 +558,13 @@ void WinSalGraphics::DrawTextLayout(const CommonSalLayout& rLayout) if (xTexture) pImpl->DrawMask(*xTexture, salColor, aDC.getTwoRect()); - ::SelectFont(aDC.getCompatibleHDC(), hOrigFont); + ::SelectFont(aDC.getCompatibleHDC(), hOFont); pImpl->PostDraw(); } } + + SelectObject(hDC, hOrigFont); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx index ed65a8698d70..633e97c6670e 100644 --- a/vcl/win/window/salframe.cxx +++ b/vcl/win/window/salframe.cxx @@ -2184,7 +2184,7 @@ static void ImplSalFrameSetInputContext( HWND hWnd, const SalInputContext* pCont // specified by this font name; but it seems to decide whether // to use that font's horizontal or vertical variant based on a // '@' in front of this font name. - ImplGetLogFontFromFontSelect(hDC, pContext->mpFont, + ImplGetLogFontFromFontSelect(hDC, &pContext->mpFont->GetFontSelectPattern(), nullptr, aLogFont); ReleaseDC( pFrame->mhWnd, hDC ); ImmSetCompositionFontW( hIMC, &aLogFont ); |