[Libreoffice-commits] core.git: Branch 'private/jmux/qt5_fixes' - 992 commits - accessibility/inc accessibility/source android/source avmedia/source basctl/inc basctl/source basctl/uiconfig basegfx/source basic/qa basic/source bin/check-elf-dynamic-objects bin/gla11y bin/oss-fuzz-build.sh bin/run bridges/inc bridges/Library_cpp_uno.mk bridges/source canvas/source canvas/workben chart2/inc chart2/qa chart2/source chart2/uiconfig comphelper/CppunitTest_comphelper_test.mk comphelper/qa comphelper/source compilerplugins/clang configmgr/source configure.ac connectivity/source cppcanvas/inc cppcanvas/source cppuhelper/source cui/CppunitTest_cui_dialogs_test_2.mk cui/CppunitTest_cui_dialogs_test_3.mk cui/CppunitTest_cui_dialogs_test_4.mk cui/inc cui/source cui/uiconfig dbaccess/inc dbaccess/Library_dbahsql.mk dbaccess/source dbaccess/uiconfig desktop/inc desktop/Module_desktop.mk desktop/qa desktop/source desktop/uiconfig desktop/unx dictionaries distro-configs/LibreOfficeHaiku.conf download.lst drawing layer/source editeng/inc editeng/qa editeng/source editeng/uiconfig embeddedobj/source emfio/inc emfio/source extensions/source extensions/uiconfig extensions/UIConfig_sbibliography.mk external/gpgmepp external/hsqldb external/icu external/libassuan external/libcmis external/libgpg-error external/liborcus external/libxml2 external/libxslt external/lxml external/Module_external.mk external/pdfium extras/CustomTarget_tplpresnt.mk extras/Gallery_backgrounds.mk extras/Module_extras.mk extras/Package_gallsystem.mk extras/Package_gallwwwback.mk extras/Package_tplpresnt.mk extras/README extras/source filter/source filter/uiconfig forms/source formula/source formula/uiconfig fpicker/source fpicker/uiconfig framework/inc framework/source helpcontent2 hwpfilter/source i18nlangtag/source i18npool/source icon-themes/elementary_svg icon-themes/galaxy idlc/source idl/inc idl/source include/avmedia include/comphelper include/connectivity include/dbaccess include/editeng include/filter include/form ula include/i18nlangtag include/i18nutil include/LibreOfficeKit include/o3tl include/oox include/osl include/sal include/sax include/sfx2 include/svl include/svtools include/svx include/test include/tools include/unotools include/vbahelper include/vcl include/xmloff ios/CustomTarget_iOS_link.mk ios/CustomTarget_iOS_setup.mk ios/LibreOfficeLight ios/welcome.odt jvmfwk/plugins libreofficekit/qa libreofficekit/source lingucomponent/source linguistic/source lotuswordpro/inc lotuswordpro/Library_lwpft.mk lotuswordpro/source Makefile.fetch Makefile.in odk/CustomTarget_build-examples.mk odk/examples offapi/com offapi/type_reference officecfg/Configuration_officecfg.mk officecfg/registry oox/inc oox/source package/source postprocess/CustomTarget_images.mk postprocess/CustomTarget_registry.mk qadevOOo/.classpath qadevOOo/Jar_OOoRunner.mk qadevOOo/objdsc qadevOOo/runner qadevOOo/tests readlicense_oo/license reportdesign/inc reportdesign/source reportdesign/uiconfig RepositoryExternal.mk Repos itory.mk sal/cppunittester sal/Library_sal.mk sal/osl sal/qa sal/rtl sax/Library_sax.mk sax/qa sax/source scaddins/source sccomp/qa sccomp/source sc/CppunitTest_sc_bugfix_test.mk sc/CppunitTest_sc_filters_test.mk sc/CppunitTest_sc_shapeobj.mk sc/inc sc/Module_sc.mk sc/qa scripting/source sc/sdi sc/source sc/uiconfig sc/UIConfig_scalc.mk sdext/README sdext/source sd/inc sd/qa sd/source sd/uiconfig setup_native/CustomTarget_scripts.mk setup_native/Library_getuid.mk setup_native/Module_setup_native.mk setup_native/scripts sfx2/inc sfx2/Library_sfx.mk sfx2/source sfx2/uiconfig shell/Executable_senddoc.mk shell/Library_smplmail.mk shell/Module_shell.mk shell/source shell/StaticLibrary_simplemapi.mk slideshow/inc slideshow/source solenv/bin solenv/clang-format solenv/CompilerTest_compilerplugins_clang.mk solenv/flatpak-manifest.in solenv/gbuild solenv/sanitizers solenv/vs soltools/mkdepend starmath/inc starmath/source starmath/uiconfig stoc/source svgio/inc svgio/Library_svgio.mk svgio/so urce svl/Library_svl.mk svl/qa svl/source svtools/inc svtools/qa svtools/source svtools/uiconfig svx/CppunitTest_svx_unit.mk svx/inc svx/Library_svx.mk svx/qa svx/sdi svx/source svx/uiconfig sw/CppunitTest_sw_odfimport.mk sw/inc sw/Library_swui.mk sw/qa sw/sdi sw/source sw/uiconfig sw/UIConfig_swriter.mk sysui/CustomTarget_deb.mk sysui/CustomTarget_rpm.mk sysui/CustomTarget_solaris.mk sysui/desktop test/Library_subsequenttest.mk test/source toolkit/inc toolkit/source tools/inc tools/Library_tl.mk tools/qa tools/source translations ucb/source uitest/calc_tests uitest/impress_tests uitest/writer_tests UnoControls/inc UnoControls/source unotools/source uui/inc uui/source uui/uiconfig vbahelper/inc vbahelper/source vcl/android vcl/backendtest vcl/CppunitTest_vcl_bitmap_test.mk vcl/CppunitTest_vcl_fontmetric.mk vcl/CustomTarget_qt5_moc.mk vcl/Executable_svpclient.mk vcl/headless vcl/inc vcl/ios vcl/Library_vcl.mk vcl/Library_vclplug_kde4.mk vcl/Library_vclplug_qt5.mk vcl/opengl vcl/osx v cl/qa vcl/qt5 vcl/quartz vcl/README.vars vcl/source vcl/uiconfig vcl/unx vcl/win vcl/workben wizards/source writerfilter/inc writerfilter/source writerperfect/source writerperfect/uiconfig xmlhelp/source xmloff/inc xmloff/source xmlsecurity/CppunitTest_xmlsecurity_signing.mk xmlsecurity/inc xmlsecurity/qa xmlsecurity/source xmlsecurity/uiconfig xmlsecurity/util

Jan-Marek Glogowski glogow at fbihome.de
Fri Mar 9 21:53:26 UTC 2018


Rebased ref, commits from common ancestor:
commit 9295c543bb015880daa912a577f8a021d9da0b29
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Mar 9 11:48:27 2018 +0100

    The minimal supported Qt5 version is 5.6
    
    The gtk3_kde5 file picker needs Qt 5.6 for the use of
    QFileDialog::setSupportedSchemes and QList::constLast.
    
    So just require this Qt5 version generally.
    
    Change-Id: I1ae5673da17d84d11a9dd4e60da3cea17fad38e2

diff --git a/configure.ac b/configure.ac
index 6eacbc878174..b16c57482b5e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -10956,10 +10956,17 @@ then
     if test "$QMAKE5" = "no"; then
         AC_MSG_ERROR([Qmake not found.  Please specify the root of your Qt5 installation by exporting QT5DIR before running "configure".])
     else
-        qmake5_test_ver="`$QMAKE5 -v 2>&1 | sed -n -e '/^Using Qt version 5\./p'`"
+        qmake5_test_ver="`$QMAKE5 -v 2>&1 | $SED -n -e 's/^Using Qt version \(5\.[[0-9.]]\+\).*$/\1/p'`"
         if test -z "$qmake5_test_ver"; then
             AC_MSG_ERROR([Wrong qmake for Qt5 found. Please specify the root of your Qt5 installation by exporting QT5DIR before running "configure".])
         fi
+        qmake5_minor_version="`echo $qmake5_test_ver | cut -d. -f2`"
+        qt5_minimal_minor="6"
+        if test "$qmake5_minor_version" -lt "$qt5_minimal_minor"; then
+            AC_MSG_ERROR([The minimal supported Qt5 version is 5.${qt5_minimal_minor}, but your 'qmake -v' reports Qt5 version $qmake5_test_ver.])
+        else
+            AC_MSG_NOTICE([Detected Qt5 version: $qmake5_test_ver])
+        fi
     fi
 
     qt5_incdirs="`$QMAKE5 -query QT_INSTALL_HEADERS` $qt5_incdirs"
commit 6e95276f7c31222528e96c6b6f19a44b6591a568
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Mar 9 11:06:26 2018 +0100

    fixup refactor
    
    Change-Id: Ia7ae09f81e476915fb9a4614ddae3ee64f5755f0

diff --git a/vcl/inc/fontinstance.hxx b/vcl/inc/fontinstance.hxx
index 5f15c3ce1710..159ecf9d3d1f 100644
--- a/vcl/inc/fontinstance.hxx
+++ b/vcl/inc/fontinstance.hxx
@@ -109,10 +109,10 @@ inline void LogicalFontInstance::ReleaseHbFont()
 
 inline void LogicalFontInstance::DecodeHbTag(const hb_tag_t nTableTag, char* pTagName)
 {
-    pTagName[0] = (char)(nTableTag >> 24);
-    pTagName[1] = (char)(nTableTag >> 16);
-    pTagName[2] = (char)(nTableTag >> 8);
-    pTagName[3] = (char)nTableTag;
+    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;
 }
 
commit 48cf6d16aac9a0976a09b46117fd6164dc7382f0
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date:   Thu Mar 1 14:57:58 2018 +0100

    WaE: -Wunused-variable
    
    Change-Id: I58f012ddc2c5030b0e3e215b9cab4e89abf06c2b

diff --git a/vcl/inc/unx/x11_cursors/null_curs.h b/vcl/inc/unx/x11_cursors/null_curs.h
index d74b462cba9b..ebeee4e6ffc5 100644
--- a/vcl/inc/unx/x11_cursors/null_curs.h
+++ b/vcl/inc/unx/x11_cursors/null_curs.h
@@ -20,6 +20,5 @@
 #define nullcurs_height 4
 #define nullcurs_x_hot 2
 #define nullcurs_y_hot 2
-static unsigned char nullcurs_bits[] = { 0x00, 0x00, 0x00, 0x00 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/x11_cursors/null_mask.h b/vcl/inc/unx/x11_cursors/null_mask.h
index bc23e9c9729b..71f08a94afcf 100644
--- a/vcl/inc/unx/x11_cursors/null_mask.h
+++ b/vcl/inc/unx/x11_cursors/null_mask.h
@@ -18,6 +18,5 @@
  */
 #define nullmask_width 4
 #define nullmask_height 4
-static unsigned char nullmask_bits[] = { 0x00, 0x00, 0x00, 0x00 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/app/saldisp.cxx b/vcl/unx/generic/app/saldisp.cxx
index a8fb3c542a64..85e65bb26a0c 100644
--- a/vcl/unx/generic/app/saldisp.cxx
+++ b/vcl/unx/generic/app/saldisp.cxx
@@ -1498,6 +1498,9 @@ KeySym SalDisplay::GetKeySym( XKeyEvent        *pEvent,
 }
 
 // Pointer
+static unsigned char nullmask_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+static unsigned char nullcurs_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+
 #define MAKE_BITMAP( name ) \
     XCreateBitmapFromData( pDisp_, \
                            DefaultRootWindow( pDisp_ ), \
diff --git a/vcl/unx/gtk/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx
index 7c9a3d1e0fbc..689fa071ce5b 100644
--- a/vcl/unx/gtk/gtkdata.cxx
+++ b/vcl/unx/gtk/gtkdata.cxx
@@ -245,6 +245,9 @@ GdkCursor* GtkSalDisplay::getFromXBM( const unsigned char *pBitmap,
               &aBlack, &aWhite, nXHot, nYHot);
 }
 
+static unsigned char nullmask_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+static unsigned char nullcurs_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+
 #define MAKE_CURSOR( vcl_name, name ) \
     case vcl_name: \
         pCursor = getFromXBM( name##curs##_bits, name##mask##_bits, \
diff --git a/vcl/unx/gtk3/gtk3gtkdata.cxx b/vcl/unx/gtk3/gtk3gtkdata.cxx
index fd5b47f0b626..024dac2a5014 100644
--- a/vcl/unx/gtk3/gtk3gtkdata.cxx
+++ b/vcl/unx/gtk3/gtk3gtkdata.cxx
@@ -213,7 +213,10 @@ GdkCursor* GtkSalDisplay::getFromXBM( const unsigned char *pBitmap,
     return cursor;
 }
 
-#define MAKE_CURSOR( vcl_name, name ) \
+static unsigned char nullmask_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+static unsigned char nullcurs_bits[] = { 0x00, 0x00, 0x00, 0x00 };
+
+#define MAKE_CURSOR( vcl_name, name )           \
     case vcl_name: \
         pCursor = getFromXBM( name##curs##_bits, name##mask##_bits, \
                               name##curs_width, name##curs_height, \
commit 31475096afd11c5a08a0aaa6a13963bc5afba118
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Feb 20 12:43:02 2018 +0100

    Add missing die and help functions
    
    Change-Id: Ic2e6138b1ba1a8031a80e4e58f468b6c0f7a4de3

diff --git a/bin/check-elf-dynamic-objects b/bin/check-elf-dynamic-objects
index ea2d67e31ff4..c4da7668e54e 100755
--- a/bin/check-elf-dynamic-objects
+++ b/bin/check-elf-dynamic-objects
@@ -15,6 +15,24 @@ set -euo pipefail
 PARA=1
 check_path="${INSTDIR:-.}"
 
+help()
+{
+    cat << "EOF"
+    -d <dir>  directory to check
+    -p        run unbound parallel checks
+    -h        help
+EOF
+    [ -z "${1:-}" ] && exit 0
+}
+
+die()
+{
+    echo "$1"
+    echo
+    help 1
+    exit 1
+}
+
 while [ "${1:-}" != "" ]; do
     parm=${1%%=*}
     arg=${1#*=}
@@ -28,12 +46,18 @@ while [ "${1:-}" != "" ]; do
     case "${parm}" in
         --dir|-d)
 	    if [ "$has_arg" ] ; then
-		check_path=$arg
+		check_path="$arg"
 	    else
 		shift
-		check_path=$1
+		check_path="$1"
 	    fi
-            ;;
+	    if [ ! -d "$check_path" ]; then
+		die "Invalid directory '$check_path'"
+	    fi
+	    ;;
+        -h)
+	    help
+	    ;;
         -p)
 	    # this sound counter intuitive. but the idea
             # is to possibly support -p <n>
commit accc0d4a4cad5500a8f8acc59bc24cf4037532ae
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Feb 20 12:29:37 2018 +0100

    Qt5 some SalLAyout painting support
    
    Don't know the glyphs are missing...
    
    Change-Id: I40834192e712af6190de8df98c10afa54d8c76e4

diff --git a/vcl/qt5/Qt5Graphics_Text.cxx b/vcl/qt5/Qt5Graphics_Text.cxx
index 75b46c2adb37..a457759a3c22 100644
--- a/vcl/qt5/Qt5Graphics_Text.cxx
+++ b/vcl/qt5/Qt5Graphics_Text.cxx
@@ -20,12 +20,14 @@
 #include "Qt5Graphics.hxx"
 #include "Qt5FontFace.hxx"
 #include "Qt5Font.hxx"
+#include "Qt5Painter.hxx"
 
 #include <vcl/fontcharmap.hxx>
 
 #include <CommonSalLayout.hxx>
 #include <PhysicalFontCollection.hxx>
 
+#include <QtGui/QGlyphRun>
 #include <QtGui/QFontDatabase>
 #include <QtGui/QRawFont>
 #include <QtCore/QStringList>
@@ -61,7 +63,7 @@ void Qt5Graphics::GetFontMetric(ImplFontMetricDataRef& rFMD, int nFallbackLevel)
     std::vector<uint8_t> rHhea(aHheaTable.data(), aHheaTable.data() + aHheaTable.size());
 
     QByteArray aOs2Table = aRawFont.fontTable("OS/2");
-    std::vector<uint8_t> rOS2(aHheaTable.data(), aHheaTable.data() + aHheaTable.size());
+    std::vector<uint8_t> rOS2(aOs2Table.data(), aOs2Table.data() + aOs2Table.size());
 
     rFMD->ImplCalcLineSpacing(rHhea, rOS2, aRawFont.unitsPerEm());
 
@@ -146,6 +148,33 @@ std::unique_ptr<SalLayout> Qt5Graphics::GetTextLayout(ImplLayoutArgs&, int nFall
     return std::unique_ptr<SalLayout>();
 }
 
-void Qt5Graphics::DrawTextLayout(const CommonSalLayout&) {}
+void Qt5Graphics::DrawTextLayout(const CommonSalLayout &rLayout )
+{
+    const Qt5Font* pFont = static_cast<const Qt5Font*>(&rLayout.getFont());
+    assert( pFont );
+    QRawFont aRawFont(QRawFont::fromFont( *pFont ));
+
+    QVector<quint32> glyphIndexes;
+    QVector<QPointF> positions;
+
+    Point aPos;
+    const GlyphItem* pGlyph;
+    int nStart = 0;
+    while (rLayout.GetNextGlyphs(1, &pGlyph, aPos, nStart))
+    {
+        glyphIndexes.push_back(pGlyph->maGlyphId);
+        positions.push_back(QPointF(aPos.X(), aPos.Y()));
+    }
+
+    QGlyphRun aGlyphRun;
+    aGlyphRun.setPositions( positions );
+    aGlyphRun.setGlyphIndexes( glyphIndexes );
+    aGlyphRun.setRawFont( aRawFont );
+
+    Qt5Painter aPainter(*this);
+    QColor aColor = QColor::fromRgb(QRgb(m_aTextColor));
+    aPainter.setPen(aColor);
+    aPainter.drawGlyphRun( QPointF(), aGlyphRun );
+}
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 763d5bf2a12be6e90277c81de2582fd820a66cbe
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Feb 20 12:24:12 2018 +0100

    Qt5 minimal "native" file picker
    
    Change-Id: I99d8213d23b09b6cb1e398359ad05c8fa702a8e0

diff --git a/vcl/CustomTarget_qt5_moc.mk b/vcl/CustomTarget_qt5_moc.mk
index 60d5df34d405..20b2da3ef280 100644
--- a/vcl/CustomTarget_qt5_moc.mk
+++ b/vcl/CustomTarget_qt5_moc.mk
@@ -10,6 +10,7 @@
 $(eval $(call gb_CustomTarget_CustomTarget,vcl/qt5))
 
 $(call gb_CustomTarget_get_target,vcl/qt5) : \
+	$(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5FilePicker.moc \
 	$(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5Instance.moc \
 	$(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5Timer.moc \
 	$(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5Widget.moc \
diff --git a/vcl/Library_vclplug_qt5.mk b/vcl/Library_vclplug_qt5.mk
index 2a2bbc5c3f0e..5cbf8e881213 100644
--- a/vcl/Library_vclplug_qt5.mk
+++ b/vcl/Library_vclplug_qt5.mk
@@ -80,6 +80,7 @@ endif
 $(eval $(call gb_Library_add_exception_objects,vclplug_qt5,\
     vcl/qt5/Qt5Bitmap \
     vcl/qt5/Qt5Data \
+    vcl/qt5/Qt5FilePicker \
     vcl/qt5/Qt5Font \
     vcl/qt5/Qt5FontFace \
     vcl/qt5/Qt5Frame \
diff --git a/vcl/qt5/Qt5FilePicker.cxx b/vcl/qt5/Qt5FilePicker.cxx
new file mode 100644
index 000000000000..cb599b6822a7
--- /dev/null
+++ b/vcl/qt5/Qt5FilePicker.cxx
@@ -0,0 +1,787 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Qt5FilePicker.hxx"
+#include <Qt5FilePicker.moc>
+
+#include "Qt5Frame.hxx"
+#include "Qt5Tools.hxx"
+#include "Qt5Widget.hxx"
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ControlActions.hpp>
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <cppuhelper/interfacecontainer.h>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <QtCore/QDebug>
+#include <QtCore/QRegularExpression>
+#include <QtCore/QThread>
+#include <QtCore/QUrl>
+#include <QtGui/QClipboard>
+#include <QtGui/QWindow>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QComboBox>
+#include <QtWidgets/QGridLayout>
+#include <QtWidgets/QHBoxLayout>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QMessageBox>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QWidget>
+
+#include <unx/geninst.h>
+#include <strings.hrc>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::com::sun::star::ui::dialogs::TemplateDescription;
+using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds;
+using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+    uno::Sequence<OUString> SAL_CALL FilePicker_getSupportedServiceNames()
+    {
+        uno::Sequence<OUString> aRet(3);
+        aRet[0] = "com.sun.star.ui.dialogs.FilePicker";
+        aRet[1] = "com.sun.star.ui.dialogs.SystemFilePicker";
+        aRet[2] = "com.sun.star.ui.dialogs.Qt5FilePicker";
+        return aRet;
+    }
+}
+
+Qt5FilePicker::Qt5FilePicker( QFileDialog::FileMode eMode )
+    : Qt5FilePicker_Base( m_aHelperMutex )
+{
+SAL_DEBUG( "Qt5FilePicker::Qt5FilePicker" );
+    m_pFileDialog = new QFileDialog();
+    m_pOptionsDialog = new QDialog();
+
+    m_pFileDialog->setFileMode( eMode );
+//    m_pFileDialog->setWindowModality( Qt::WindowModal );
+    m_pFileDialog->setWindowModality( Qt::ApplicationModal );
+    m_pOptionsDialog->setWindowModality( Qt::WindowModal );
+
+    setMultiSelectionMode( false );
+
+    // XExecutableDialog functions
+    connect( this, SIGNAL( setTitleSignal( const OUString & ) ),
+             this, SLOT( setTitleSlot( const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( executeSignal() ),
+             this, SLOT( executeSlot() ), Qt::BlockingQueuedConnection );
+
+    // XFilePicker functions
+    connect( this, SIGNAL( setMultiSelectionModeSignal( bool ) ),
+             this, SLOT( setMultiSelectionModeSlot( bool ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( setDefaultNameSignal( const OUString & ) ),
+             this, SLOT( setDefaultNameSlot( const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( setDisplayDirectorySignal( const OUString & ) ),
+             this, SLOT( setDisplayDirectorySlot( const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( getDisplayDirectorySignal() ),
+             this, SLOT( getDisplayDirectorySlot() ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( getFilesSignal() ),
+             this, SLOT( getFilesSlot() ), Qt::BlockingQueuedConnection );
+
+    // XFilterManager functions
+    connect( this, SIGNAL( appendFilterSignal( const OUString &, const OUString & ) ),
+             this, SLOT( appendFilterSlot( const OUString &, const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( setCurrentFilterSignal( const OUString & ) ),
+             this, SLOT( setCurrentFilterSlot( const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( getCurrentFilterSignal() ),
+             this, SLOT( getCurrentFilterSlot() ), Qt::BlockingQueuedConnection );
+
+    // XFilterGroupManager functions
+    connect( this, SIGNAL( appendFilterGroupSignal( const OUString &, const css::uno::Sequence< css::beans::StringPair > & ) ),
+             this, SLOT( appendFilterGroupSlot( const OUString &, const css::uno::Sequence< css::beans::StringPair > & ) ), Qt::BlockingQueuedConnection );
+
+    // XFilePickerControlAccess functions
+    connect( this, SIGNAL( setValueSignal( sal_Int16, sal_Int16, const css::uno::Any & ) ),
+             this, SLOT( setValueSlot( sal_Int16, sal_Int16, const css::uno::Any & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( getValueSignal( sal_Int16, sal_Int16 ) ),
+             this, SLOT( getValueSlot( sal_Int16, sal_Int16 ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( enableControlSignal( sal_Int16, bool ) ),
+             this, SLOT( enableControlSlot( sal_Int16, bool ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( setLabelSignal( sal_Int16, const OUString & ) ),
+             this, SLOT( setLabelSlot( sal_Int16, const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( getLabelSignal( sal_Int16 ) ),
+             this, SLOT( getLabelSlot( sal_Int16 ) ), Qt::BlockingQueuedConnection );
+
+    // XFilePicker2 functions
+    connect( this, SIGNAL( getSelectedFilesSignal() ),
+             this, SLOT( getSelectedFilesSlot() ), Qt::BlockingQueuedConnection );
+
+    // XInitialization
+    connect( this, SIGNAL( initializeSignal( const css::uno::Sequence< css::uno::Any > & ) ),
+             this, SLOT( initializeSlot( const css::uno::Sequence< css::uno::Any > & ) ), Qt::BlockingQueuedConnection );
+
+    // Destructor proxy
+    connect( this, SIGNAL( cleanupProxySignal() ), this, SLOT( cleanupProxy() ), Qt::BlockingQueuedConnection );
+
+    // XFilePickerListener notifications
+    connect( m_pFileDialog, SIGNAL( filterSelected(const QString&) ), this, SLOT( filterSelected(const QString&) ));
+    connect( m_pFileDialog, SIGNAL( selectionChanged() ), this, SLOT( selectionChanged() ));
+}
+
+Qt5FilePicker::~Qt5FilePicker()
+{
+    cleanupProxy();
+}
+
+void Qt5FilePicker::cleanupProxy()
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT cleanupProxySignal();
+    }
+    delete m_pOptionsDialog;
+}
+
+void SAL_CALL Qt5FilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener )
+{
+    SolarMutexGuard aGuard;
+    m_xListener = xListener;
+}
+
+void SAL_CALL Qt5FilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& )
+{
+    SolarMutexGuard aGuard;
+    m_xListener.clear();
+}
+
+void SAL_CALL Qt5FilePicker::setTitle( const OUString &title )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT setTitleSignal( title );
+    }
+
+    m_pOptionsDialog->setWindowTitle( toQString(title) );
+}
+
+sal_Int16 SAL_CALL Qt5FilePicker::execute()
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT executeSignal();
+    }
+
+    vcl::Window *pWindow = ::Application::GetActiveTopWindow();
+    assert( pWindow );
+    Qt5Widget *pTransientParent = nullptr;
+    QWindow *pTransientWindow = nullptr;
+    if( pWindow )
+    {
+        Qt5Frame *pFrame = dynamic_cast<Qt5Frame *>( pWindow->ImplGetFrame() );
+        assert( pFrame );
+        if( pFrame )
+        {
+            pTransientParent = static_cast<Qt5Widget *>( pFrame->GetQWidget() );
+            pTransientWindow = pTransientParent->window()->windowHandle();
+        }
+    }
+
+    m_pFileDialog->setNameFilters( m_aNamedFilterList );
+    if( !m_aCurrentFilterTitle.isNull() )
+    {
+        int i = 0;
+        for( ; i < m_aFilterTitleList.size(); ++i )
+            if( m_aCurrentFilterTitle == m_aFilterTitleList[ i ] )
+            {
+                m_pFileDialog->selectNameFilter( m_aNamedFilterList[ i ] );
+                break;
+            }
+        assert( i < m_aFilterTitleList.size() );
+    }
+
+    if( pTransientParent )
+    {
+        m_pFileDialog->show();
+        m_pFileDialog->window()->windowHandle()->setTransientParent( pTransientWindow );
+        m_pFileDialog->setFocusProxy( pTransientParent );
+//        pTransientParent->setMouseTracking( false );
+    }
+    int result = m_pFileDialog->exec();
+    if( pTransientParent )
+//        pTransientParent->setMouseTracking( true );
+    if( QFileDialog::Rejected == result )
+        return ExecutableDialogResults::CANCEL;
+
+    if ( !m_aCustomWidgetsMap.empty() )
+    {
+        m_pFilenameLabel->setText( m_pFileDialog->selectedUrls()[ 0 ].url() );
+        QString filter = m_pFileDialog->selectedNameFilter();
+        int pos = filter.indexOf(" (");
+        if( pos >= 0 )
+            filter.truncate( pos );
+        m_pFilterLabel->setText( filter );
+
+        if( pTransientParent )
+        {
+            m_pOptionsDialog->show();
+            m_pOptionsDialog->window()->windowHandle()->setTransientParent( pTransientWindow );
+            m_pOptionsDialog->setFocusProxy( pTransientParent );
+        }
+        result = m_pOptionsDialog->exec();
+        if( QFileDialog::Rejected == result )
+            return ExecutableDialogResults::CANCEL;
+    }
+
+    return ExecutableDialogResults::OK;
+}
+
+void SAL_CALL Qt5FilePicker::setMultiSelectionMode( sal_Bool multiSelect )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT setMultiSelectionModeSignal( multiSelect );
+    }
+
+    if( multiSelect )
+        m_pFileDialog->setFileMode( QFileDialog::ExistingFiles );
+    else
+        m_pFileDialog->setFileMode( QFileDialog::ExistingFile );
+}
+
+void SAL_CALL Qt5FilePicker::setDefaultName( const OUString &name )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT setDefaultNameSignal( name );
+    }
+    m_pFileDialog->selectFile( toQString( name ) );
+}
+
+void SAL_CALL Qt5FilePicker::setDisplayDirectory( const OUString &dir )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT setDisplayDirectorySignal( dir );
+    }
+    m_pFileDialog->setDirectory( toQString( dir ) );
+}
+
+OUString SAL_CALL Qt5FilePicker::getDisplayDirectory()
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT getDisplayDirectorySignal();
+    }
+    return toOUString( m_pFileDialog->directoryUrl().toString() );
+}
+
+uno::Sequence< OUString > SAL_CALL Qt5FilePicker::getFiles()
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT getFilesSignal();
+    }
+    uno::Sequence< OUString > seq = getSelectedFiles();
+    if (seq.getLength() > 1)
+        seq.realloc(1);
+    return seq;
+}
+
+uno::Sequence< OUString > SAL_CALL Qt5FilePicker::getSelectedFiles()
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT getSelectedFilesSignal();
+    }
+    QList<QUrl> urls = m_pFileDialog->selectedUrls();
+    uno::Sequence< OUString > seq( urls.size() );
+    int i = 0;
+    foreach( const QUrl& url, urls )
+        seq[ i++ ]= toOUString( url.toString() );
+    return seq;
+}
+
+void SAL_CALL Qt5FilePicker::appendFilter( const OUString &title, const OUString &filter )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT appendFilterSignal( title, filter );
+    }
+
+    QString t = toQString(title);
+    QString f = toQString(filter);
+
+    // '/' need to be escaped else they are assumed to be mime types by kfiledialog
+    //see the docs
+    t.replace("/", "\\/");
+
+    int pos = t.indexOf(" (");
+    if( pos >= 0 )
+        t.truncate( pos );
+
+    // openoffice gives us filters separated by ';' qt dialogs just want space separated
+    f.replace(";", " ");
+
+    // make sure "*.*" is not used as "all files"
+    f.replace("*.*", "*");
+
+    m_aFilterTitleList.append( toQString( title ) );
+    m_aNamedFilterList.append( QString("%1 (%2)").arg(t).arg(f) );
+}
+
+void SAL_CALL Qt5FilePicker::setCurrentFilter( const OUString &title )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT setCurrentFilterSignal( title );
+    }
+
+    m_aCurrentFilterTitle = toQString( title );
+}
+
+OUString SAL_CALL Qt5FilePicker::getCurrentFilter()
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT getCurrentFilterSignal();
+    }
+
+    QString filter = m_pFileDialog->selectedNameFilter();
+    for( int i = 0; i < m_aNamedFilterList.size(); ++i )
+        if( filter == m_aNamedFilterList[ i ] )
+            return toOUString( m_aFilterTitleList[ i ] );
+    SAL_DEBUG( "vcl.qt5 " << m_aNamedFilterList.size() << " Unknown filter: " << toOUString( filter ) );
+    assert( !"Selected filter not in filter list?! " );
+    return OUString( "" );
+}
+
+void SAL_CALL Qt5FilePicker::appendFilterGroup( const OUString& rGroupTitle, const uno::Sequence<beans::StringPair>& filters)
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT appendFilterGroupSignal( rGroupTitle, filters );
+    }
+
+    const sal_uInt16 length = filters.getLength();
+    for (sal_uInt16 i = 0; i < length; ++i)
+    {
+        beans::StringPair aPair = filters[i];
+        appendFilter( aPair.First, aPair.Second );
+    }
+}
+
+void SAL_CALL Qt5FilePicker::setValue( sal_Int16 controlId, sal_Int16 nControlAction, const uno::Any &value )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT setValueSignal( controlId, nControlAction, value );
+    }
+
+    if (m_aCustomWidgetsMap.contains( controlId )) {
+        QCheckBox* cb = dynamic_cast<QCheckBox*>( m_aCustomWidgetsMap.value( controlId ));
+        if (cb)
+            cb->setChecked(value.get<bool>());
+    }
+    else
+        SAL_WARN( "vcl", "set label on unknown control " << controlId );
+}
+
+uno::Any SAL_CALL Qt5FilePicker::getValue( sal_Int16 controlId, sal_Int16 nControlAction )
+{
+    if (CHECKBOX_AUTOEXTENSION == controlId)
+        // We ignore this one and rely on QFileDialog to provide the function.
+        // Always return false, to pretend we do not support this, otherwise
+        // LO core would try to be smart and cut the extension in some places,
+        // interfering with QFileDialog's handling of it. QFileDialog also
+        // saves the value of the setting, so LO core is not needed for that either.
+        return uno::Any( false );
+
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT getValueSignal( controlId, nControlAction );
+    }
+
+    uno::Any res(false);
+    if (m_aCustomWidgetsMap.contains( controlId )) {
+        QCheckBox* cb = dynamic_cast<QCheckBox*>( m_aCustomWidgetsMap.value( controlId ));
+        if (cb)
+            res <<= cb->isChecked();
+    }
+    else
+        SAL_WARN( "vcl", "get value on unknown control " << controlId );
+
+    return res;
+}
+
+void SAL_CALL Qt5FilePicker::enableControl( sal_Int16 controlId, sal_Bool enable )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT enableControlSignal( controlId, enable );
+    }
+
+    if (m_aCustomWidgetsMap.contains( controlId ))
+        m_aCustomWidgetsMap.value( controlId )->setEnabled( enable );
+    else
+        SAL_WARN( "vcl", "enable unknown control " << controlId );
+}
+
+void SAL_CALL Qt5FilePicker::setLabel( sal_Int16 controlId, const OUString &label )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT setLabelSignal( controlId, label );
+    }
+
+    if (m_aCustomWidgetsMap.contains( controlId )) {
+        QCheckBox* cb = dynamic_cast<QCheckBox*>( m_aCustomWidgetsMap.value( controlId ));
+        if (cb)
+            cb->setText( toQString(label) );
+    }
+    else
+        SAL_WARN( "vcl", "set label on unknown control " << controlId );
+}
+
+OUString SAL_CALL Qt5FilePicker::getLabel(sal_Int16 controlId)
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT getLabelSignal( controlId );
+    }
+
+    QString label;
+    if (m_aCustomWidgetsMap.contains( controlId )) {
+        QCheckBox* cb = dynamic_cast<QCheckBox*>( m_aCustomWidgetsMap.value( controlId ));
+        if (cb)
+            label = cb->text();
+    }
+    else
+        SAL_WARN( "vcl", "get label on unknown control " << controlId );
+
+    return toOUString(label);
+}
+
+QString Qt5FilePicker::getResString(const char *pResId)
+{
+    QString aResString;
+
+    if (pResId == nullptr)
+        return aResString;
+
+    aResString = toQString(VclResId(pResId));
+
+    return aResString.replace('~', '&');
+}
+
+void Qt5FilePicker::addCustomControl(QGridLayout *pLayout, sal_Int16 controlId)
+{
+    QWidget* widget = nullptr;
+    QWidget* label = nullptr;
+    const char* resId = nullptr;
+
+    switch (controlId)
+    {
+        case CHECKBOX_AUTOEXTENSION:
+            resId = STR_FPICKER_AUTO_EXTENSION;
+            break;
+        case CHECKBOX_PASSWORD:
+            resId = STR_FPICKER_PASSWORD;
+            break;
+        case CHECKBOX_FILTEROPTIONS:
+            resId = STR_FPICKER_FILTER_OPTIONS;
+            break;
+        case CHECKBOX_READONLY:
+            resId = STR_FPICKER_READONLY;
+            break;
+        case CHECKBOX_LINK:
+            resId = STR_FPICKER_INSERT_AS_LINK;
+            break;
+        case CHECKBOX_PREVIEW:
+            resId = STR_FPICKER_SHOW_PREVIEW;
+            break;
+        case CHECKBOX_SELECTION:
+            resId = STR_FPICKER_SELECTION;
+            break;
+        case PUSHBUTTON_PLAY:
+            resId = STR_FPICKER_PLAY;
+            break;
+        case LISTBOX_VERSION:
+            resId = STR_FPICKER_VERSION;
+            break;
+        case LISTBOX_TEMPLATE:
+            resId = STR_FPICKER_TEMPLATES;
+            break;
+        case LISTBOX_IMAGE_TEMPLATE:
+            resId = STR_FPICKER_IMAGE_TEMPLATE;
+            break;
+        case LISTBOX_VERSION_LABEL:
+        case LISTBOX_TEMPLATE_LABEL:
+        case LISTBOX_IMAGE_TEMPLATE_LABEL:
+        case LISTBOX_FILTER_SELECTOR:
+            break;
+    }
+
+    switch (controlId)
+    {
+        case CHECKBOX_AUTOEXTENSION:
+        case CHECKBOX_PASSWORD:
+        case CHECKBOX_FILTEROPTIONS:
+        case CHECKBOX_READONLY:
+        case CHECKBOX_LINK:
+        case CHECKBOX_PREVIEW:
+        case CHECKBOX_SELECTION:
+            widget = new QCheckBox(getResString(resId), m_pOptionsDialog);
+            break;
+        case PUSHBUTTON_PLAY:
+            break;
+        case LISTBOX_VERSION:
+        case LISTBOX_TEMPLATE:
+        case LISTBOX_IMAGE_TEMPLATE:
+        case LISTBOX_FILTER_SELECTOR:
+            label = new QLabel( getResString(resId), m_pOptionsDialog );
+            widget = new QComboBox( m_pOptionsDialog );
+            break;
+        case LISTBOX_VERSION_LABEL:
+        case LISTBOX_TEMPLATE_LABEL:
+        case LISTBOX_IMAGE_TEMPLATE_LABEL:
+            break;
+    }
+
+    if( widget )
+    {
+        const int row = pLayout->rowCount();
+        if( label )
+            pLayout->addWidget( label, row, 0 );
+        pLayout->addWidget( widget, row, 1 );
+        m_aCustomWidgetsMap.insert( controlId, widget );
+    }
+}
+
+void SAL_CALL Qt5FilePicker::initialize( const uno::Sequence<uno::Any> &args )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SolarMutexReleaser aReleaser;
+        return Q_EMIT initializeSignal( args );
+    }
+
+    m_aNamedFilterList.clear();
+    m_aFilterTitleList.clear();
+    m_aCurrentFilterTitle.clear();
+
+    // parameter checking
+    uno::Any arg;
+    if (args.getLength() == 0)
+    {
+        throw lang::IllegalArgumentException(
+                "no arguments",
+                static_cast< XFilePicker2* >( this ), 1 );
+    }
+
+    arg = args[0];
+
+    if (( arg.getValueType() != cppu::UnoType<sal_Int16>::get()) &&
+        ( arg.getValueType() != cppu::UnoType<sal_Int8>::get()))
+    {
+        throw lang::IllegalArgumentException(
+                "invalid argument type",
+                static_cast< XFilePicker2* >( this ), 1 );
+    }
+
+    QGridLayout *pLayout = new QGridLayout();
+    m_pOptionsDialog->setLayout( pLayout );
+    pLayout->addWidget( new QLabel( "Filename:" ), 0, 0 );
+    m_pFilenameLabel = new QLabel();
+    pLayout->addWidget( m_pFilenameLabel, 0, 1 );
+    pLayout->addWidget( new QLabel( "Type:" ), 1, 0 );
+    m_pFilterLabel = new QLabel();
+    pLayout->addWidget( m_pFilterLabel, 1, 1 );
+
+    sal_Int16 templateId = -1;
+    arg >>= templateId;
+
+    QFileDialog::AcceptMode acceptMode = QFileDialog::AcceptOpen;
+    switch ( templateId )
+    {
+        case FILEOPEN_SIMPLE:
+            break;
+
+        case FILESAVE_SIMPLE:
+            acceptMode = QFileDialog::AcceptSave;
+            break;
+
+        case FILESAVE_AUTOEXTENSION:
+            acceptMode = QFileDialog::AcceptSave;
+            addCustomControl( pLayout, CHECKBOX_AUTOEXTENSION );
+            break;
+
+        case FILESAVE_AUTOEXTENSION_PASSWORD:
+            acceptMode = QFileDialog::AcceptSave;
+            addCustomControl( pLayout, CHECKBOX_AUTOEXTENSION );
+            addCustomControl( pLayout, CHECKBOX_PASSWORD );
+            break;
+
+        case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
+            acceptMode = QFileDialog::AcceptSave;
+            addCustomControl( pLayout, CHECKBOX_AUTOEXTENSION );
+            addCustomControl( pLayout, CHECKBOX_PASSWORD );
+            addCustomControl( pLayout, CHECKBOX_FILTEROPTIONS );
+            break;
+
+        case FILESAVE_AUTOEXTENSION_SELECTION:
+            acceptMode = QFileDialog::AcceptSave;
+            addCustomControl( pLayout, CHECKBOX_AUTOEXTENSION );
+            addCustomControl( pLayout, CHECKBOX_SELECTION );
+            break;
+
+        case FILESAVE_AUTOEXTENSION_TEMPLATE:
+            acceptMode = QFileDialog::AcceptSave;
+            addCustomControl( pLayout, CHECKBOX_AUTOEXTENSION );
+            addCustomControl( pLayout, LISTBOX_TEMPLATE );
+            break;
+
+        case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
+            addCustomControl( pLayout, CHECKBOX_LINK );
+            addCustomControl( pLayout, CHECKBOX_PREVIEW );
+            addCustomControl( pLayout, LISTBOX_IMAGE_TEMPLATE );
+            break;
+
+        case FILEOPEN_PLAY:
+            addCustomControl( pLayout, PUSHBUTTON_PLAY );
+            break;
+
+        case FILEOPEN_LINK_PLAY:
+            addCustomControl( pLayout, CHECKBOX_LINK );
+            addCustomControl( pLayout, PUSHBUTTON_PLAY );
+            break;
+
+        case FILEOPEN_READONLY_VERSION:
+            addCustomControl( pLayout, CHECKBOX_READONLY );
+            addCustomControl( pLayout, LISTBOX_VERSION );
+            break;
+
+        case FILEOPEN_LINK_PREVIEW:
+            addCustomControl( pLayout, CHECKBOX_LINK );
+            addCustomControl( pLayout, CHECKBOX_PREVIEW );
+            break;
+
+        case FILEOPEN_PREVIEW:
+            addCustomControl( pLayout, CHECKBOX_PREVIEW );
+            break;
+
+        default:
+            throw lang::IllegalArgumentException(
+                    "Unknown template",
+                    static_cast< XFilePicker2* >( this ),
+                    1 );
+    }
+
+    if( !m_aCustomWidgetsMap.empty() )
+    {
+        QHBoxLayout *pHBoxLayout = new QHBoxLayout();
+        pLayout->addLayout( pHBoxLayout, pLayout->rowCount(), 0, 1, 2 );
+        pHBoxLayout->addStretch();
+        QPushButton *pButton = new QPushButton( "Ok" );
+        connect( pButton, SIGNAL(clicked()), m_pOptionsDialog, SLOT(accept()) );
+        pHBoxLayout->addWidget( pButton );
+        pButton = new QPushButton( "Cancel" );
+        connect( pButton, SIGNAL(clicked()), m_pOptionsDialog, SLOT(reject()) );
+        pHBoxLayout->addWidget( pButton );
+    }
+
+    const char *resId = nullptr;
+    switch ( acceptMode )
+    {
+    case QFileDialog::AcceptOpen:
+        resId = STR_FPICKER_OPEN;
+        break;
+    case QFileDialog::AcceptSave:
+        resId = STR_FPICKER_SAVE;
+        m_pFileDialog->setFileMode( QFileDialog::AnyFile );
+        break;
+    }
+
+    m_pFileDialog->setAcceptMode( acceptMode );
+    m_pFileDialog->setWindowTitle( getResString(resId) );
+}
+
+void SAL_CALL Qt5FilePicker::cancel()
+{
+
+}
+
+void SAL_CALL Qt5FilePicker::disposing( const lang::EventObject &rEvent )
+{
+    uno::Reference<XFilePickerListener> xFilePickerListener( rEvent.Source, uno::UNO_QUERY );
+
+    if ( xFilePickerListener.is() )
+    {
+        removeFilePickerListener( xFilePickerListener );
+    }
+}
+
+OUString SAL_CALL Qt5FilePicker::getImplementationName()
+{
+    return OUString( "com.sun.star.ui.dialogs.Qt5FilePicker" );
+}
+
+sal_Bool SAL_CALL Qt5FilePicker::supportsService( const OUString& ServiceName )
+{
+    return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL Qt5FilePicker::getSupportedServiceNames()
+{
+    return FilePicker_getSupportedServiceNames();
+}
+
+void Qt5FilePicker::filterSelected(const QString &)
+{
+    FilePickerEvent aEvent;
+    aEvent.ElementId = LISTBOX_FILTER;
+    SAL_INFO( "vcl", "filter changed" );
+    if (m_xListener.is())
+        m_xListener->controlStateChanged( aEvent );
+}
+
+void Qt5FilePicker::selectionChanged()
+{
+    FilePickerEvent aEvent;
+    SAL_INFO( "vcl", "file selection changed" );
+    if (m_xListener.is())
+        m_xListener->fileSelectionChanged( aEvent );
+}
+
+OUString Qt5FilePicker::getDirectory()
+{
+    uno::Sequence< OUString > seq = getSelectedFiles();
+    if (seq.getLength() > 1)
+        seq.realloc(1);
+    return seq[ 0 ];
+}
+
+void Qt5FilePicker::setDescription( const OUString& )
+{
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5FilePicker.hxx b/vcl/qt5/Qt5FilePicker.hxx
new file mode 100644
index 000000000000..1aa19b3459f4
--- /dev/null
+++ b/vcl/qt5/Qt5FilePicker.hxx
@@ -0,0 +1,244 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/compbase.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
+#include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <osl/conditn.hxx>
+#include <osl/mutex.hxx>
+
+#include <rtl/ustrbuf.hxx>
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QHash>
+#include <QtWidgets/QFileDialog>
+
+class QGridLayout;
+class QLabel;
+class QWidget;
+
+typedef ::cppu::WeakComponentImplHelper
+    < css::ui::dialogs::XFilePicker3
+    , css::ui::dialogs::XFilePickerControlAccess
+    , css::ui::dialogs::XFolderPicker2
+    , css::lang::XInitialization
+    , css::lang::XServiceInfo
+    > Qt5FilePicker_Base;
+
+class Qt5FilePicker
+    : public QObject
+    , public Qt5FilePicker_Base
+{
+    Q_OBJECT
+
+protected:
+    css::uno::Reference< css::ui::dialogs::XFilePickerListener > m_xListener;
+
+    QFileDialog* m_pFileDialog;    ///< the non-extendable file picker dialog
+
+    osl::Mutex   m_aHelperMutex;   ///< mutex used by the WeakComponentImplHelper
+
+    QStringList  m_aNamedFilterList;     ///< named filter list for the QFileDialog
+    QStringList  m_aFilterTitleList;     ///< the original filter titles
+    QString      m_aCurrentFilterTitle;  ///< the current filter title
+
+    QDialog                    *m_pOptionsDialog;    ///< an extra options dialog window
+    QLabel                     *m_pFilenameLabel;    ///< label to display the filename
+    QLabel                     *m_pFilterLabel;      ///< label to display the filter
+    QHash<sal_Int16, QWidget*>  m_aCustomWidgetsMap; ///< map of SAL control ID's to widget
+
+public:
+    explicit Qt5FilePicker( QFileDialog::FileMode );
+    virtual ~Qt5FilePicker() override;
+
+    // XFilePickerNotifier
+    virtual void SAL_CALL addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) override;
+    virtual void SAL_CALL removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) override;
+
+    // XFilterManager functions
+    virtual void SAL_CALL appendFilter( const OUString &rTitle, const OUString &rFilter ) override;
+    virtual void SAL_CALL setCurrentFilter( const OUString &rTitle ) override;
+    virtual OUString SAL_CALL getCurrentFilter() override;
+
+    // XFilterGroupManager functions
+    virtual void SAL_CALL appendFilterGroup( const OUString &rGroupTitle, const css::uno::Sequence< css::beans::StringPair > &rFilters ) override;
+
+    // XCancellable
+    virtual void SAL_CALL cancel( ) override;
+
+    // XExecutableDialog functions
+    virtual void SAL_CALL setTitle( const OUString &rTitle ) override;
+    virtual sal_Int16 SAL_CALL execute() override;
+
+    // XFilePicker functions
+    virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) override;
+    virtual void SAL_CALL setDefaultName( const OUString &rName ) override;
+    virtual void SAL_CALL setDisplayDirectory( const OUString &rDirectory ) override;
+    virtual OUString SAL_CALL getDisplayDirectory() override;
+    virtual css::uno::Sequence< OUString > SAL_CALL getFiles() override;
+
+    // XFilePickerControlAccess functions
+    virtual void SAL_CALL setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const css::uno::Any &rValue ) override;
+    virtual css::uno::Any SAL_CALL getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) override;
+    virtual void SAL_CALL enableControl( sal_Int16 nControlId, sal_Bool bEnable ) override;
+    virtual void SAL_CALL setLabel( sal_Int16 nControlId, const OUString &rLabel ) override;
+    virtual OUString SAL_CALL getLabel( sal_Int16 nControlId ) override;
+
+    // XFilePicker2 functions
+    virtual css::uno::Sequence< OUString > SAL_CALL getSelectedFiles() override;
+
+    // XInitialization
+    virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any > &rArguments ) override;
+
+    // XEventListener
+    /// @throws css::uno::RuntimeException
+    virtual void SAL_CALL disposing( const css::lang::EventObject &rEvent );
+    using cppu::WeakComponentImplHelperBase::disposing;
+
+    // XServiceInfo
+    virtual OUString SAL_CALL getImplementationName() override;
+    virtual sal_Bool SAL_CALL supportsService( const OUString &rServiceName ) override;
+    virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+    // XFolderPicker functions
+    virtual OUString SAL_CALL getDirectory() override;
+    virtual void SAL_CALL setDescription( const OUString& rDescription ) override;
+
+private Q_SLOTS:
+    // XExecutableDialog functions
+    /// @throws css::uno::RuntimeException
+    void setTitleSlot( const OUString &rTitle ) { return setTitle( rTitle ); }
+    /// @throws css::uno::RuntimeException
+    sal_Int16 executeSlot() { return execute(); }
+
+    // XFilePicker functions
+    /// @throws css::uno::RuntimeException
+    void setMultiSelectionModeSlot( bool bMode ) { return setMultiSelectionMode( bMode ); }
+    /// @throws css::uno::RuntimeException
+    void setDefaultNameSlot( const OUString &rName ) { return setDefaultName( rName ); }
+    /// @throws css::uno::RuntimeException
+    void setDisplayDirectorySlot( const OUString &rDirectory ) { return setDisplayDirectory( rDirectory ); }
+    /// @throws css::uno::RuntimeException
+    OUString getDisplayDirectorySlot() { return getDisplayDirectory(); }
+    /// @throws css::uno::RuntimeException
+    css::uno::Sequence< OUString > getFilesSlot() { return getFiles(); }
+
+    // XFilterManager functions
+    /// @throws css::lang::IllegalArgumentException
+    /// @throws css::uno::RuntimeException
+    void appendFilterSlot( const OUString &rTitle, const OUString &rFilter ) { return appendFilter( rTitle, rFilter ); }
+    /// @throws css::lang::IllegalArgumentException
+    /// @throws css::uno::RuntimeException
+    void setCurrentFilterSlot( const OUString &rTitle ) { return setCurrentFilter( rTitle ); }
+    /// @throws css::uno::RuntimeException
+    OUString getCurrentFilterSlot() { return getCurrentFilter(); }
+
+    // XFilterGroupManager functions
+    /// @throws css::lang::IllegalArgumentException
+    /// @throws css::uno::RuntimeException
+    void appendFilterGroupSlot( const OUString &rGroupTitle, const css::uno::Sequence< css::beans::StringPair > &rFilters ) { return appendFilterGroup( rGroupTitle, rFilters ); }
+
+    // XFilePickerControlAccess functions
+    /// @throws css::uno::RuntimeException
+    void setValueSlot( sal_Int16 nControlId, sal_Int16 nControlAction, const css::uno::Any &rValue ) { return setValue( nControlId, nControlAction, rValue ); }
+    /// @throws css::uno::RuntimeException
+    css::uno::Any getValueSlot( sal_Int16 nControlId, sal_Int16 nControlAction ) { return getValue( nControlId, nControlAction ); }
+    /// @throws css::uno::RuntimeException
+    void enableControlSlot( sal_Int16 nControlId, bool bEnable ) { return enableControl( nControlId, bEnable ); }
+    /// @throws css::uno::RuntimeException
+    void setLabelSlot( sal_Int16 nControlId, const OUString &rLabel ) { return setLabel( nControlId, rLabel ); }
+    /// @throws css::uno::RuntimeException
+    OUString getLabelSlot( sal_Int16 nControlId ) { return getLabel( nControlId ); }
+
+    // XFilePicker2 functions
+    /// @throws css::uno::RuntimeException
+    css::uno::Sequence< OUString > getSelectedFilesSlot() { return getSelectedFiles(); }
+
+    // XInitialization
+    /// @throws css::uno::Exception
+    /// @throws css::uno::RuntimeException
+    void initializeSlot( const css::uno::Sequence< css::uno::Any > &rArguments ) { return initialize( rArguments ); }
+
+Q_SIGNALS:
+    // XExecutableDialog functions
+    void setTitleSignal( const OUString &rTitle );
+    sal_Int16 executeSignal();
+
+    // XFilePicker functions
+    void setMultiSelectionModeSignal( bool bMode );
+    void setDefaultNameSignal( const OUString &rName );
+    void setDisplayDirectorySignal( const OUString &rDirectory );
+    OUString getDisplayDirectorySignal();
+    css::uno::Sequence< OUString > getFilesSignal();
+
+    // XFilterManager functions
+    void appendFilterSignal( const OUString &rTitle, const OUString &rFilter );
+    void setCurrentFilterSignal( const OUString &rTitle );
+    OUString getCurrentFilterSignal();
+
+    // XFilterGroupManager functions
+    void appendFilterGroupSignal( const OUString &rGroupTitle, const css::uno::Sequence< css::beans::StringPair > &rFilters );
+
+    // XFilePickerControlAccess functions
+    void setValueSignal( sal_Int16 nControlId, sal_Int16 nControlAction, const css::uno::Any &rValue );
+    css::uno::Any getValueSignal( sal_Int16 nControlId, sal_Int16 nControlAction );
+    void enableControlSignal( sal_Int16 nControlId, bool bEnable );
+    void setLabelSignal( sal_Int16 nControlId, const OUString &rLabel );
+    OUString getLabelSignal( sal_Int16 nControlId );
+
+    // XFilePicker2 functions
+    css::uno::Sequence< OUString > getSelectedFilesSignal() ;
+
+    // XInitialization
+    void initializeSignal( const css::uno::Sequence< css::uno::Any > &rArguments );
+
+    // Destructor proxy
+    void cleanupProxySignal();
+
+private:
+    Qt5FilePicker( const Qt5FilePicker& ) = delete;
+    Qt5FilePicker& operator=( const Qt5FilePicker& ) = delete;
+
+    // add a custom control widget to the options dialog
+    void addCustomControl(QGridLayout *pLayout, sal_Int16 controlId);
+
+    static QString getResString(const char* pRedId);
+
+private Q_SLOTS:
+    void cleanupProxy();
+
+    // emit XFilePickerListener controlStateChanged event
+    void filterSelected(const QString &);
+    // emit XFilePickerListener fileSelectionChanged event
+//    void urlSelected(const QUrl &);
+
+    void selectionChanged();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5Instance.cxx b/vcl/qt5/Qt5Instance.cxx
index b9464fa7fc20..69acffb151dd 100644
--- a/vcl/qt5/Qt5Instance.cxx
+++ b/vcl/qt5/Qt5Instance.cxx
@@ -20,19 +20,20 @@
 #include "Qt5Instance.hxx"
 #include <Qt5Instance.moc>
 
-#include "Qt5Frame.hxx"
+#include "Qt5Bitmap.hxx"
 #include "Qt5Data.hxx"
+#include "Qt5FilePicker.hxx"
+#include "Qt5Frame.hxx"
+#include "Qt5Object.hxx"
 #include "Qt5Timer.hxx"
 #include "Qt5VirtualDevice.hxx"
-#include "Qt5Object.hxx"
-#include "Qt5Bitmap.hxx"
 
 #include <headless/svpvd.hxx>
 
+#include <QtCore/QAbstractEventDispatcher>
 #include <QtCore/QThread>
 #include <QtWidgets/QApplication>
 #include <QtWidgets/QWidget>
-#include <QtCore/QAbstractEventDispatcher>
 
 #include <vclpluginapi.h>
 #include <sal/log.hxx>
@@ -180,6 +181,20 @@ void Qt5Instance::ProcessEvent(SalUserEvent aEvent)
     aEvent.m_pFrame->CallCallback(aEvent.m_nEvent, aEvent.m_pData);
 }
 
+css::uno::Reference< css::ui::dialogs::XFilePicker2 >
+Qt5Instance::createFilePicker( const css::uno::Reference< css::uno::XComponentContext > & )
+{
+    return css::uno::Reference< css::ui::dialogs::XFilePicker2 >(
+        new Qt5FilePicker( QFileDialog::ExistingFile ) );
+}
+
+css::uno::Reference< css::ui::dialogs::XFolderPicker2 >
+Qt5Instance::createFolderPicker( const css::uno::Reference< css::uno::XComponentContext > & )
+{
+    return css::uno::Reference< css::ui::dialogs::XFolderPicker2 >(
+        new Qt5FilePicker( QFileDialog::Directory ) );
+}
+
 extern "C" {
 VCLPLUG_QT5_PUBLIC SalInstance* create_SalInstance()
 {
diff --git a/vcl/qt5/Qt5Instance.hxx b/vcl/qt5/Qt5Instance.hxx
index 22005d91e978..00a0d6bde0f1 100644
--- a/vcl/qt5/Qt5Instance.hxx
+++ b/vcl/qt5/Qt5Instance.hxx
@@ -100,6 +100,12 @@ public:
 
     virtual void TriggerUserEventProcessing() override;
     virtual void ProcessEvent(SalUserEvent aEvent) override;
+
+    virtual css::uno::Reference< css::ui::dialogs::XFilePicker2 > createFilePicker(
+        const css::uno::Reference< css::uno::XComponentContext >& ) override;
+
+    virtual css::uno::Reference< css::ui::dialogs::XFolderPicker2 > createFolderPicker(
+        const css::uno::Reference< css::uno::XComponentContext >& ) override;
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 84da17c83f78ba52d47540b0857d60f362000fab
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

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 0aecb5e16a1c..864b505f3965 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -747,22 +747,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 68758028d662..2a2bbc5c3f0e 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..5f15c3ce1710 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 SetWidthFactor(double nFactor) { m_nAveWidthFactor = nFactor; }
+    double GetWidthFactor() 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 DecodeHbTag(const hb_tag_t nTableTag, char* pTagName);
+
 protected:
     explicit LogicalFontInstance(const PhysicalFontFace&, const FontSelectPattern&);
 
+    // Takes ownership of pHbFace and destroys it!
+    hb_font_t* InitHbFont(hb_face_t* pHbFace) const;
+    virtual hb_font_t* ImplInitHbFont();
+    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::DecodeHbTag(const hb_tag_t nTableTag, char* pTagName)
+{
+    pTagName[0] = (char)(nTableTag >> 24);
+    pTagName[1] = (char)(nTableTag >> 16);
+    pTagName[2] = (char)(nTableTag >> 8);
+    pTagName[3] = (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 3cf3f48c3863..69bd53759ae2 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;
@@ -93,8 +95,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; }
 
@@ -106,9 +106,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 afeddb2ecc96..d6d9ac021c4a 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..51e87e8a1958 100644
--- a/vcl/qt5/Qt5Font.cxx
+++ b/vcl/qt5/Qt5Font.cxx
@@ -17,8 +17,38 @@
  *   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::DecodeHbTag(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(reinterpret_cast<const char*>(aTable.data()), nLength,
+                               HB_MEMORY_MODE_READONLY, 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 c9ad0a4b6538..e232bf30a8ef 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( MAKE_SALCOLOR(0xFF, 0xFF, 0XFF) )
     , m_eCompositionMode( QPainter::CompositionMode_SourceOver )
     , m_pFontCollection( nullptr )
-    , m_pFontData{ nullptr, }
     , m_pTextStyle{ nullptr, }
     , m_aTextColor( MAKE_SALCOLOR(0x00, 0x00, 0x00) )
 {
diff --git a/vcl/qt5/Qt5Graphics.hxx b/vcl/qt5/Qt5Graphics.hxx
index 6e8332356d49..6c8812f1ec2e 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];
     SalColor m_aTextColor;
 
diff --git a/vcl/qt5/Qt5Graphics_Text.cxx b/vcl/qt5/Qt5Graphics_Text.cxx
index 8524dafe0cff..75b46c2adb37 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..246537e69843 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,45 @@ 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)
+{
+    char pTagName[5];
+    LogicalFontInstance::DecodeHbTag(nTableTag, pTagName);
+
+    sal_uLong nLength = 0;
+    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);
+    }
+
+    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);
diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index 0f80f839ae35..939731e3cb08 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 3e05d704ffc0..e147cc68b30f 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..fffb8e5bf28f 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,45 @@ 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_face_destroy(pHbFace);
+    return pHbFont;
+}
+
+hb_font_t* LogicalFontInstance::ImplInitHbFont()
+{
+    return nullptr;
+}
+
+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 5c53673ead25..6b68b69842cf 100644
--- a/vcl/source/font/fontselect.cxx
+++ b/vcl/source/font/fontselect.cxx
@@ -19,6 +19,8 @@
 
 #include <sal/config.h>
 
+#include <fontselect.hxx>
+
 #include <PhysicalFontFace.hxx>
 #include <svdata.hxx>
 
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index e1afd6edeaa9..3664401237b2 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,7 @@ bool CommonSalLayout::HasVerticalAlternate(sal_UCS4 aChar, sal_UCS4 aVariationSe
 
 bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
 {
-    hb_face_t* pHbFace = hb_font_get_face(mpHbFont);
+    hb_face_t* pHbFace = hb_font_get_face(mpFont->GetHbFont());
 
     int nGlyphCapacity = 2 * (rArgs.mnEndCharPos - rArgs.mnMinCharPos);
     Reserve(nGlyphCapacity);
@@ -546,17 +298,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)
@@ -647,6 +400,7 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
         if (bRightToLeft)
             std::reverse(aSubRuns.begin(), aSubRuns.end());
 
+        hb_font_t *pHbFont = mpFont->GetHbFont();
         for (const auto& aSubRun : aSubRuns)
         {
             hb_buffer_clear_contents(pHbBuffer);
@@ -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);
@@ -740,7 +494,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 ,
@@ -832,12 +586,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 0013055af95c..c7bbce1f27f4 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -1763,7 +1763,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 2f073742dea6..23b9ad08620b 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>
@@ -149,7 +150,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;
@@ -175,7 +177,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)
@@ -441,7 +443,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;
 
@@ -451,7 +453,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;
 }
@@ -466,13 +468,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;
@@ -536,4 +538,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);

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list