[Libreoffice-commits] core.git: bin/check-elf-dynamic-objects vcl/CppunitTest_vcl_fontmetric.mk vcl/inc vcl/Library_vcl.mk vcl/Library_vclplug_kde4.mk vcl/Library_vclplug_qt5.mk vcl/qt5 vcl/quartz vcl/source vcl/unx vcl/win

Jan-Marek Glogowski glogow at fbihome.de
Mon May 7 22:55:50 UTC 2018


 bin/check-elf-dynamic-objects                  |    4 
 vcl/CppunitTest_vcl_fontmetric.mk              |    4 
 vcl/Library_vcl.mk                             |   18 -
 vcl/Library_vclplug_kde4.mk                    |    1 
 vcl/Library_vclplug_qt5.mk                     |    3 
 vcl/inc/CommonSalLayout.hxx                    |   68 -----
 vcl/inc/fontinstance.hxx                       |   40 +++
 vcl/inc/quartz/salgdi.h                        |    8 
 vcl/inc/salwtype.hxx                           |    4 
 vcl/inc/svdata.hxx                             |    1 
 vcl/inc/unx/freetype_glyphcache.hxx            |    2 
 vcl/inc/unx/glyphcache.hxx                     |   12 
 vcl/inc/win/salgdi.h                           |    7 
 vcl/inc/win/winlayout.hxx                      |   11 
 vcl/qt5/Qt5Font.cxx                            |   31 ++
 vcl/qt5/Qt5Font.hxx                            |   22 -
 vcl/qt5/Qt5FontFace.cxx                        |    2 
 vcl/qt5/Qt5Graphics.cxx                        |    3 
 vcl/qt5/Qt5Graphics.hxx                        |    1 
 vcl/qt5/Qt5Graphics_Text.cxx                   |   11 
 vcl/quartz/ctfonts.cxx                         |   44 +++
 vcl/quartz/salgdi.cxx                          |    2 
 vcl/source/font/fontcache.cxx                  |    1 
 vcl/source/font/fontinstance.cxx               |   40 +++
 vcl/source/font/fontselect.cxx                 |    2 
 vcl/source/gdi/CommonSalLayout.cxx             |  305 ++-----------------------
 vcl/source/window/window.cxx                   |    2 
 vcl/unx/generic/gdi/cairotextrender.cxx        |   15 -
 vcl/unx/generic/glyphs/freetype_glyphcache.cxx |   22 -
 vcl/unx/generic/glyphs/glyphcache.cxx          |   26 ++
 vcl/unx/generic/print/genpspgraphics.cxx       |    2 
 vcl/win/gdi/salfont.cxx                        |   16 -
 vcl/win/gdi/winlayout.cxx                      |   95 ++++++-
 vcl/win/window/salframe.cxx                    |    2 
 34 files changed, 377 insertions(+), 450 deletions(-)

New commits:
commit bdccb7e9991d83029eb2f2f11327b54534a00db8
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Dec 26 15:14:31 2017 +0000

    Refactor CommonSalLayout font handling
    
    Moves all platform specific code from CommonSalLayout into the
    platform specific plugins. This way the vcl library won't depend
    on the Qt5 libraries and the Qt5Font header can be moved into the
    qt5 VCL plugin.
    
    While at it, switch the CommonSalLayouts font reference from the
    FontSelectPattern to the LogicalFontInstance and also add the
    harfbuzz font handling to the instance.
    
    Change-Id: Ida910b8d88837ea949a2f84394ccc0cfae153060
    Reviewed-on: https://gerrit.libreoffice.org/47408
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Khaled Hosny <khaledhosny at eglug.org>

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
similarity index 71%
rename from vcl/inc/qt5/Qt5Font.hxx
rename to 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 );


More information about the Libreoffice-commits mailing list