[Libreoffice-commits] core.git: Branch 'private/jmux/qt5_fixes' - 1347 commits - accessibility/inc accessibility/source android/Bootstrap android/README android/source avmedia/source basctl/inc basctl/source basctl/uiconfig basegfx/Library_basegfx.mk basegfx/source basegfx/test basic/inc basic/source bin/check-elf-dynamic-objects bin/find-unneeded-includes bin/gbuild-to-ide bin/gla11y bin/sanitize-blacklist.txt bridges/Library_cpp_uno.mk bridges/source canvas/source canvas/workben chart2/CppunitTest_chart2_dump.mk chart2/CppunitTest_chart2_export.mk chart2/CppunitTest_chart2_import.mk chart2/CppunitTest_chart2_pivot_chart_test.mk chart2/CppunitTest_chart2_trendcalculators.mk chart2/CppunitTest_chart2_xshape.mk chart2/inc chart2/source chart2/uiconfig cli_ure/source comphelper/source compilerplugins/clang config_host/config_gpgme.h.in config_host.mk.in configmgr/source configure.ac connectivity/Jar_ConnectivityTools.mk connectivity/qa connectivity/source cppcanvas/CppunitTest_cppcanvas_emfplus.mk cppcanvas/Library_cppcanvas.mk cppcanvas/qa cppcanvas/source cui/inc cui/qa cui/source cui/uiconfig cui/UIConfig_cui.mk dbaccess/CppunitTest_dbaccess_embeddeddb_performancetest.mk dbaccess/CppunitTest_dbaccess_hsqlbinary_import.mk dbaccess/CppunitTest_dbaccess_hsqldb_test.mk dbaccess/CppunitTest_dbaccess_hsqlschema_import.mk dbaccess/CppunitTest_dbaccess_RowSetClones.mk dbaccess/inc dbaccess/Library_dbahsql.mk dbaccess/Module_dbaccess.mk dbaccess/qa dbaccess/README.vars dbaccess/source dbaccess/uiconfig desktop/CppunitTest_desktop_lib.mk desktop/inc desktop/qa desktop/source dictionaries distro-configs/LibreOfficeFlatpak.conf download.lst drawinglayer/source dtrans/source editeng/inc editeng/qa editeng/source embeddedobj/source embedserv/source emfio/qa emfio/source extensions/inc extensions/qa extensions/source extensions/uiconfig external/firebird external/hunspell external/libepubgen external/libmspub external/libstaroffice external/lxml external/more_fonts external/python3 extra s/source filter/inc filter/source filter/uiconfig forms/qa forms/source formula/source fpicker/source fpicker/test fpicker/uiconfig framework/inc framework/Library_fwl.mk framework/source framework/util g helpcompiler/source helpcontent2 hwpfilter/source i18nlangtag/qa i18nlangtag/source i18npool/inc i18npool/source i18nutil/source icon-themes/breeze icon-themes/breeze_dark icon-themes/breeze_svg icon-themes/colibre icon-themes/colibre_svg icon-themes/crystal icon-themes/elementary icon-themes/elementary_svg icon-themes/galaxy icon-themes/sifr icon-themes/sifr_dark icon-themes/sifr_svg icon-themes/tango icon-themes/tango_svg idlc/inc idlc/source idl/inc idl/source include/avmedia include/basegfx include/basic include/canvas include/comphelper include/connectivity include/cppuhelper include/drawinglayer include/editeng include/filter include/LibreOfficeKit include/o3tl include/oox include/sal include/sfx2 include/svl include/svtools include/svx include/test include/toolkit include/to ols include/ucbhelper include/vbahelper include/vcl include/xmloff instsetoo_native/inc_openoffice ios/LibreOfficeLight io/source jvmaccess/source jvmfwk/plugins jvmfwk/source l10ntools/inc l10ntools/source libreofficekit/qa libreofficekit/source lingucomponent/source linguistic/source lotuswordpro/inc lotuswordpro/qa lotuswordpro/source Makefile.in mysqlc/Library_mysqlc.mk mysqlc/source odk/CustomTarget_html.mk odk/examples odk/README offapi/com offapi/UnoApi_offapi.mk offapi/util officecfg/Configuration_officecfg.mk officecfg/files.mk officecfg/registry onlineupdate/source oox/source package/qa package/source postprocess/CustomTarget_images.mk postprocess/CustomTarget_registry.mk postprocess/qa postprocess/Rdb_services.mk pyuno/qa pyuno/source qadevOOo/Jar_OOoRunner.mk qadevOOo/objdsc qadevOOo/.project qadevOOo/README qadevOOo/tests readlicense_oo/license README.md reportdesign/inc reportdesign/source sal/Library_sal.mk sal/osl sax/source scaddins/source sc/common_unoapi_tests.mk sc/CppunitTest_sc_addin_functions_test.mk sc/CppunitTest_sc_anchor_test.mk sc/CppunitTest_sc_annotationobj.mk sc/CppunitTest_sc_annotationshapeobj.mk sc/CppunitTest_sc_annotationsobj.mk sc/CppunitTest_sc_arealinkobj.mk sc/CppunitTest_sc_arealinksobj.mk sc/CppunitTest_sc_array_functions_test.mk sc/CppunitTest_sc_autoformatobj.mk sc/CppunitTest_sc_bugfix_test.mk sc/CppunitTest_sc_cache_test.mk sc/CppunitTest_sc_cellcursorobj.mk sc/CppunitTest_sc_cellobj.mk sc/CppunitTest_sc_cellrangeobj.mk sc/CppunitTest_sc_cellrangesobj.mk sc/CppunitTest_sc_chart2dataprovider.mk sc/CppunitTest_sc_chart_regression_test.mk sc/CppunitTest_sc_check_data_pilot_field.mk sc/CppunitTest_sc_check_data_pilot_table.mk sc/CppunitTest_sc_check_xcell_ranges_query.mk sc/CppunitTest_sc_cond_format_merge.mk sc/CppunitTest_sc_consolidationdescriptorobj.mk sc/CppunitTest_sc_copypaste.mk sc/CppunitTest_sc_database_functions_test.mk sc/CppunitTest_sc_databaserangeobj.mk sc/CppunitTest_sc_databaserangesobj.mk sc/CppunitTe st_sc_datapilotfieldobj.mk sc/CppunitTest_sc_datapilotitemobj.mk sc/CppunitTest_sc_datapilottableobj.mk sc/CppunitTest_sc_datapilottablesobj.mk sc/CppunitTest_sc_dataprovider.mk sc/CppunitTest_sc_datatransformation.mk sc/CppunitTest_sc_datetime_functions_test.mk sc/CppunitTest_sc_ddelinkobj.mk sc/CppunitTest_sc_documentconfigurationobj.mk sc/CppunitTest_sc_editfieldobj_cell.mk sc/CppunitTest_sc_editfieldobj_header.mk sc/CppunitTest_sc_filterdescriptorbaseobj.mk sc/CppunitTest_sc_filters_test.mk sc/CppunitTest_sc_financial_functions_test.mk sc/CppunitTest_sc_functionlistobj.mk sc/CppunitTest_sc_functions_test_old.mk sc/CppunitTest_sc_headerfootercontentobj.mk sc/CppunitTest_sc_html_export_test.mk sc/CppunitTest_sc_importdescriptorbaseobj.mk sc/CppunitTest_sc_information_functions_test.mk sc/CppunitTest_sc_labelrangeobj.mk sc/CppunitTest_sc_labelrangesobj.mk sc/CppunitTest_sc_logical_functions_test.mk sc/CppunitTest_sc_macros_test.mk sc/CppunitTest_sc_mark_test.mk sc/CppunitTest_sc_ma thematical_functions_test.mk sc/CppunitTest_sc_modelobj.mk sc/CppunitTest_sc_namedrangeobj.mk sc/CppunitTest_sc_namedrangesobj.mk sc/CppunitTest_sc_new_cond_format_api.mk sc/CppunitTest_sc_opencl_test.mk sc/CppunitTest_sc_outlineobj.mk sc/CppunitTest_sc_parallelism.mk sc/CppunitTest_sc_pivottable_filters_test.mk sc/CppunitTest_sc_rangelst_test.mk sc/CppunitTest_sc_range_test.mk sc/CppunitTest_sc_recentfunctionsobj.mk sc/CppunitTest_sc_recordchanges.mk sc/CppunitTest_sc_scenariosobj.mk sc/CppunitTest_sc_shapeobj.mk sc/CppunitTest_sc_sheetlinkobj.mk sc/CppunitTest_sc_spreadsheet_functions_test.mk sc/CppunitTest_sc_spreadsheetsettings.mk sc/CppunitTest_sc_spreadsheetsettingsobj.mk sc/CppunitTest_sc_statistical_functions_test.mk sc/CppunitTest_sc_styleloaderobj.mk sc/CppunitTest_sc_subsequent_export_test.mk sc/CppunitTest_sc_subsequent_filters_test.mk sc/CppunitTest_sc_subtotaldescriptorbaseobj.mk sc/CppunitTest_sc_subtotalfieldobj.mk sc/CppunitTest_sc_tableconditionalentryobj.mk sc/Cpp unitTest_sc_tableconditionalformatobj.mk sc/CppunitTest_sc_tablesheetobj.mk sc/CppunitTest_sc_tablesheetsobj.mk sc/CppunitTest_sc_tablevalidationobj.mk sc/CppunitTest_sc_tabviewobj.mk sc/CppunitTest_sc_text_functions_test.mk sc/CppunitTest_sc_ucalc.mk sc/CppunitTest_sc_viewpaneobj.mk sc/inc sc/IwyuFilter_sc.yaml sc/Library_sc.mk sc/Module_sc.mk sc/qa scripting/examples scripting/java scripting/Package_ScriptsPython.mk scripting/source sc/sdi sc/source sc/uiconfig sc/UITest_autofilter.mk sc/UITest_calc_tests.mk sd/CppunitTest_sd_activex_controls_tests.mk sd/CppunitTest_sd_filters_test.mk sd/CppunitTest_sd_html_export_tests.mk sd/CppunitTest_sd_import_tests.mk sd/CppunitTest_sd_import_tests_smartart.mk sd/CppunitTest_sd_misc_tests.mk sdext/CppunitTest_sdext_pdfimport.mk sdext/Executable_pdf2xml.mk sdext/Executable_pdfunzip.mk sdext/Library_pdfimport.mk sdext/Library_PresenterScreen.mk sdext/source sd/inc sd/qa sd/source sd/uiconfig setup_native/scripts sfx2/CppunitTest_sfx2_misc.mk sf x2/inc sfx2/Library_sfx.mk sfx2/qa sfx2/source sfx2/uiconfig sfx2/UIConfig_sfx.mk shell/source slideshow/source solenv/bin solenv/clang-format solenv/CompilerTest_compilerplugins_clang.mk solenv/flatpak-manifest.in solenv/gbuild solenv/gdb solenv/sanitizers sot/CppunitTest_sot_test_sot.mk sot/inc sot/qa sot/source starmath/inc starmath/source starmath/uiconfig stoc/source stoc/test svgio/inc svgio/qa svgio/source svl/source svtools/inc svtools/Library_svt.mk svtools/qa svtools/source svtools/uiconfig svtools/util svx/inc svx/Library_svx.mk svx/qa svx/sdi svx/source svx/uiconfig svx/UIConfig_svx.mk sw/CppunitTest_sw_accessible_relation_set.mk sw/CppunitTest_sw_filters_test.mk sw/CppunitTest_sw_htmlexport.mk sw/CppunitTest_sw_htmlimport.mk sw/CppunitTest_sw_layoutwriter.mk sw/CppunitTest_sw_macros_test.mk sw/CppunitTest_sw_mailmerge.mk sw/CppunitTest_sw_odfimport.mk sw/CppunitTest_sw_ooxmlexport12.mk sw/CppunitTest_sw_ooxmlexport8.mk sw/CppunitTest_sw_ooxmlimport.mk sw/CppunitTest_sw_ rtfimport.mk sw/CppunitTest_sw_uiwriter.mk sw/CppunitTest_sw_uwriter.mk sw/CppunitTest_sw_ww8export2.mk sw/CppunitTest_sw_ww8export.mk sw/CppunitTest_sw_ww8import.mk swext/mediawiki sw/inc sw/IwyuFilter_sw.yaml sw/JunitTest_sw_complex.mk sw/Library_sw.mk sw/Module_sw.mk sw/ooxmlexport_setup.mk sw/qa sw/sdi sw/source sw/uiconfig sw/UIConfig_swriter.mk sw/UITest_writer_tests.mk test/inc test/Library_subsequenttest.mk test/Library_test.mk test/source toolkit/inc toolkit/Library_tk.mk toolkit/source tools/source ucbhelper/source ucb/source uitest/manual_tests uitest/UITest_manual_tests.mk uitest/UITest_writer_demo.mk uitest/writer_tests UnoControls/inc UnoControls/source unodevtools/source unoidl/source unotest/source unotools/source unoxml/Library_unoxml.mk unoxml/qa unoxml/source ure/source uui/inc uui/source uui/uiconfig vbahelper/source vcl/backendtest vcl/CppunitTest_vcl_fontmetric.mk vcl/CppunitTest_vcl_jpeg_read_write_test.mk vcl/CustomTarget_qt5_moc.mk vcl/headless vcl/inc vcl/L ibrary_vcl.mk vcl/Library_vclplug_kde4.mk vcl/Library_vclplug_qt5.mk vcl/opengl vcl/osx vcl/qa vcl/qt5 vcl/quartz vcl/source vcl/uiconfig vcl/unx vcl/vcl.common.component vcl/win vcl/workben winaccessibility/source wizards/source writerfilter/CppunitTest_writerfilter_rtftok.mk writerfilter/IwyuFilter_writerfilter.yaml writerfilter/source writerperfect/Library_writerperfect.mk writerperfect/qa writerperfect/source xmerge/source xmlhelp/source xmloff/inc xmloff/Library_xo.mk xmloff/qa xmloff/source xmlscript/dtd xmlscript/source xmlscript/test xmlsecurity/CppunitTest_xmlsecurity_signing.mk xmlsecurity/Executable_pdfverify.mk xmlsecurity/inc xmlsecurity/qa xmlsecurity/source xmlsecurity/util xmlsecurity/workben

Jan-Marek Glogowski glogow at fbihome.de
Mon Apr 16 01:04:27 UTC 2018


Rebased ref, commits from common ancestor:
commit 3c4c688787df1ac659ce1f82b13af5f962d45f09
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Apr 16 00:58:59 2018 +0000

    Lot of fixes
    
    Change-Id: I6aa342ead561ef736605d3f8625fb0dcd2249b62

diff --git a/basctl/source/basicide/baside2b.cxx b/basctl/source/basicide/baside2b.cxx
index a506a68e40b3..5bc3ec682f4f 100644
--- a/basctl/source/basicide/baside2b.cxx
+++ b/basctl/source/basicide/baside2b.cxx
@@ -963,6 +963,7 @@ void EditorWindow::CreateEditEngine()
     ImplSetFont();
 
     aSyntaxIdle.SetInvokeHandler( LINK( this, EditorWindow, SyntaxTimerHdl ) );
+    aSyntaxIdle.SetDebugName( "basctl EditorWindow aSyntaxIdle" );
 
     bool bWasDoSyntaxHighlight = bDoSyntaxHighlight;
     bDoSyntaxHighlight = false; // too slow for large texts...
diff --git a/sfx2/source/appl/appdispatchprovider.cxx b/sfx2/source/appl/appdispatchprovider.cxx
index a13cb5312bf6..d13a9009ee0e 100644
--- a/sfx2/source/appl/appdispatchprovider.cxx
+++ b/sfx2/source/appl/appdispatchprovider.cxx
@@ -129,7 +129,10 @@ Reference < XDispatch > SAL_CALL SfxAppDispatchProvider::queryDispatch(
     bool                bMasterCommand( false );
     Reference < XDispatch > xDisp;
     const SfxSlot* pSlot = nullptr;
-    SfxDispatcher* pAppDisp = SfxGetpApp()->GetAppDispatcher_Impl();
+    SfxApplication* pApp = SfxGetpApp();
+    if ( !pApp )
+        return xDisp;
+    SfxDispatcher* pAppDisp = pApp->GetAppDispatcher_Impl();
     if ( aURL.Protocol == "slot:" || aURL.Protocol == "commandId:" )
     {
         nId = static_cast<sal_uInt16>(aURL.Path.toInt32());
diff --git a/solenv/bin/create-tags b/solenv/bin/create-tags
index c9fd565b823f..0537caa7ee3d 100755
--- a/solenv/bin/create-tags
+++ b/solenv/bin/create-tags
@@ -11,6 +11,15 @@ ctags="ctags $@"
 saloptions="-ISAL_DELETED_FUNCTION -ISAL_OVERRIDE -ISAL_FINAL"
 omnicppoptions="--c++-kinds=+p --fields=+iaS --extra=+q"
 
+if [ "$1" -eq "-e" ]; then
+    tagfile="TAGS"
+else
+    tagfile="tags"
+fi
+
+tmpfile=$(mktemp)
+ctags="$ctags -f $tmpfile"
+
 $ctags -h "+.hdl.hrc" --langmap=c:+.hrc.src,c++:+.hdl $saloptions $omnicppoptions \
       --languages=-HTML,Java,JavaScript \
       --langdef=UNOIDL \
@@ -39,3 +48,6 @@ $ctags -h "+.hdl.hrc" --langmap=c:+.hrc.src,c++:+.hdl $saloptions $omnicppoption
       $w/UnoApiHeadersTarget/udkapi/normal \
       $w/UnoApiHeadersTarget/offapi/normal \
       $w/CustomTarget/officecfg/registry
+
+mv "$tmpfile" "$tagfile"
+
diff --git a/vcl/qt5/Qt5Bitmap.cxx b/vcl/qt5/Qt5Bitmap.cxx
index f14479fd9419..253e26d57ea9 100644
--- a/vcl/qt5/Qt5Bitmap.cxx
+++ b/vcl/qt5/Qt5Bitmap.cxx
@@ -38,18 +38,27 @@ bool Qt5Bitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPale
            && "Unsupported BitCount!");
 
     if (nBitCount == 1)
-        assert(2 == rPal.GetEntryCount());
+        assert(2 <= rPal.GetEntryCount());
     if (nBitCount == 4)
-        assert(16 == rPal.GetEntryCount());
+        assert(16 <= rPal.GetEntryCount());
     if (nBitCount == 8)
-        assert(256 == rPal.GetEntryCount());
+        assert(256 <= rPal.GetEntryCount());
 
     if (nBitCount == 4)
     {
         m_pImage.reset();
         m_aSize = rSize;
-        m_nScanline = rSize.Width() / 2 + (rSize.Width() % 2) ? 0 : 1;
-        m_pBuffer.reset(new sal_uInt8[m_nScanline * rSize.Height()]);
+        bool bFail = o3tl::checked_multiply<sal_uInt32>(rSize.Width(), nBitCount, m_nScanline);
+        if (bFail)
+        {
+            SAL_WARN("vcl.gdi", "checked multiply failed");
+            return false;
+        }
+        m_nScanline = AlignedWidth4Bytes(m_nScanline);
+        sal_uInt8 *pBuffer = nullptr;
+        if (0 != m_nScanline && 0 != rSize.Height())
+            pBuffer = new sal_uInt8[m_nScanline * rSize.Height()];
+        m_pBuffer.reset(pBuffer);
     }
     else
     {
@@ -59,7 +68,7 @@ bool Qt5Bitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPale
     m_aPalette = rPal;
 
     auto count = rPal.GetEntryCount();
-    if (nBitCount != 4 && count)
+    if (nBitCount != 4 && count && m_pImage.get())
     {
         QVector<QRgb> aColorTable(count);
         for (unsigned i = 0; i < count; ++i)
@@ -81,8 +90,14 @@ bool Qt5Bitmap::Create(const SalBitmap& rSalBmp)
     {
         m_aSize = pBitmap->m_aSize;
         m_nScanline = pBitmap->m_nScanline;
-        m_pBuffer.reset(new sal_uInt8[m_nScanline * m_aSize.Height()]);
-        memcpy(m_pBuffer.get(), pBitmap->m_pBuffer.get(), m_nScanline);
+        sal_uInt8 *pBuffer = nullptr;
+        if (0 != m_nScanline && 0 != m_aSize.Height())
+        {
+            sal_uInt32 nSize = m_nScanline * m_aSize.Height();
+            pBuffer = new sal_uInt8[nSize];
+            memcpy(pBuffer, pBitmap->m_pBuffer.get(), nSize);
+        }
+        m_pBuffer.reset(pBuffer);
         m_pImage.reset();
     }
     m_aPalette = pBitmap->m_aPalette;
@@ -107,9 +122,51 @@ bool Qt5Bitmap::Create(const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount)
 
     const Qt5Bitmap* pBitmap = static_cast<const Qt5Bitmap*>(&rSalBmp);
     if (pBitmap->m_pBuffer.get())
-        return false;
+    {
+        if (nNewBitCount != 32)
+            return false;
+
+        // convert 4bit indexed palette to 32bit ARGB
+        m_pImage.reset(new QImage(pBitmap->m_aSize.Width(), pBitmap->m_aSize.Height(), getBitFormat(nNewBitCount)));
+        m_pImage->fill(0);
+
+        // prepare a whole palette
+        const BitmapPalette& rPal = pBitmap->m_aPalette;
+        QVector<QRgb> colorTable(16);
+        int i = 0, maxEntry = pBitmap->m_aPalette.GetEntryCount();
+        assert(maxEntry <= 16 && maxEntry >= 0);
+        for (; i < maxEntry; ++i)
+            colorTable[i] = qRgb(rPal[i].GetRed(), rPal[i].GetGreen(), rPal[i].GetBlue());
+        for (; i < 16; ++i)
+            colorTable[i] = qRgb(0, 0, 0);
 
-    m_pImage.reset(new QImage(pBitmap->m_pImage->convertToFormat(getBitFormat(nNewBitCount))));
+        sal_uInt32 *image_data = reinterpret_cast<sal_uInt32*>(m_pImage->bits());
+        sal_uInt8 *buffer_data_pos = pBitmap->m_pBuffer.get();
+        sal_uInt32 nWidth = pBitmap->m_aSize.Height() / 2;
+        bool isOdd(0 != pBitmap->m_aSize.Height() % 2);
+
+        for (sal_uInt32 h = 0; h < pBitmap->m_aSize.Height(); ++h)
+        {
+            sal_uInt8 *buffer_data = buffer_data_pos;
+            buffer_data_pos += pBitmap->m_nScanline;
+            for (sal_uInt32 w = 0; w < nWidth; ++w)
+            {
+                *image_data = reinterpret_cast<sal_uInt32>(colorTable.at(*buffer_data >> 4));
+                ++image_data;
+                *image_data = reinterpret_cast<sal_uInt32>(colorTable.at(*buffer_data & 0xF));
+                ++image_data;
+                ++buffer_data;
+            }
+            if (isOdd)
+            {
+                *image_data = reinterpret_cast<sal_uInt32>(colorTable.at(*buffer_data >> 4));
+                ++image_data;
+            }
+        }
+    }
+    else
+        m_pImage.reset(new QImage(pBitmap->m_pImage->convertToFormat(getBitFormat(nNewBitCount))));
+    m_pBuffer.reset();
     return true;
 }
 
@@ -172,7 +229,7 @@ BitmapBuffer* Qt5Bitmap::AcquireBuffer(BitmapAccessMode /*nMode*/)
     switch (pBuffer->mnBitCount)
     {
         case 1:
-            pBuffer->mnFormat = ScanlineFormat::N1BitLsbPal | ScanlineFormat::TopDown;
+            pBuffer->mnFormat = ScanlineFormat::N1BitMsbPal | ScanlineFormat::TopDown;
             pBuffer->maPalette = m_aPalette;
             break;
         case 4:
diff --git a/vcl/qt5/Qt5Bitmap.hxx b/vcl/qt5/Qt5Bitmap.hxx
index 6ecdebed5ca1..c89038a28fb7 100644
--- a/vcl/qt5/Qt5Bitmap.hxx
+++ b/vcl/qt5/Qt5Bitmap.hxx
@@ -31,7 +31,7 @@ class VCL_DLLPUBLIC Qt5Bitmap : public SalBitmap
     BitmapPalette m_aPalette;
 
     // for 4bit support
-    std::unique_ptr<sal_uInt8> m_pBuffer;
+    std::unique_ptr<sal_uInt8[]> m_pBuffer;
     Size m_aSize;
     sal_uInt32 m_nScanline;
 
diff --git a/vcl/qt5/Qt5Font.cxx b/vcl/qt5/Qt5Font.cxx
index 74918a70f008..6430c2e55066 100644
--- a/vcl/qt5/Qt5Font.cxx
+++ b/vcl/qt5/Qt5Font.cxx
@@ -18,13 +18,40 @@
  */
 
 #include "Qt5Font.hxx"
+#include "Qt5Tools.hxx"
 
 #include <QtGui/QFont>
 #include <QtGui/QRawFont>
 
+static QFont::Weight GetQFontWeight(FontWeight eWeight)
+{
+    switch(eWeight)
+    {
+    case WEIGHT_THIN: return QFont::Thin;
+    case WEIGHT_ULTRALIGHT: return QFont::ExtraLight;
+    case WEIGHT_LIGHT: return QFont::Light;
+    case FontWeight_FORCE_EQUAL_SIZE:
+        assert( 0 && "FontWeight_FORCE_EQUAL_SIZE not implementable for QFont" );
+    case WEIGHT_SEMILIGHT:
+    case WEIGHT_DONTKNOW:
+    case WEIGHT_NORMAL: return QFont::Normal;
+    case WEIGHT_MEDIUM: return QFont::Medium;
+    case WEIGHT_SEMIBOLD: return QFont::DemiBold;
+    case WEIGHT_BOLD: return QFont::Bold;
+    case WEIGHT_ULTRABOLD: return QFont::ExtraBold;
+    case WEIGHT_BLACK: return QFont::Black;
+    }
+
+    // so we would get enum not handled warning
+    return QFont::Normal;
+}
+
 Qt5Font::Qt5Font(const PhysicalFontFace& rPFF, const FontSelectPattern& rFSP)
     : LogicalFontInstance(rPFF, rFSP)
 {
+    setFamily( toQString(rPFF.GetFamilyName()) );
+    setWeight( GetQFontWeight(rPFF.GetWeight()) );
+    setPixelSize( rFSP.mnHeight );
 }
 
 Qt5Font::~Qt5Font() {}
diff --git a/vcl/qt5/Qt5FontFace.cxx b/vcl/qt5/Qt5FontFace.cxx
index b7a0f0b12f9e..9ffa51cb4aac 100644
--- a/vcl/qt5/Qt5FontFace.cxx
+++ b/vcl/qt5/Qt5FontFace.cxx
@@ -44,9 +44,28 @@ Qt5FontFace::Qt5FontFace(const Qt5FontFace& rSrc)
 Qt5FontFace* Qt5FontFace::fromQFont(const QFont& rFont)
 {
     FontAttributes aFA;
-    aFA.SetFamilyName(toOUString(rFont.family()));
-    aFA.SetStyleName(toOUString(rFont.styleName()));
-    aFA.SetItalic(rFont.italic() ? ITALIC_NORMAL : ITALIC_NONE);
+    QFontInfo aFontInfo(rFont);
+    aFA.SetFamilyName(toOUString(aFontInfo.family()));
+    aFA.SetStyleName(toOUString(aFontInfo.styleName()));
+    aFA.SetItalic(aFontInfo.italic() ? ITALIC_NORMAL : ITALIC_NONE);
+    aFA.SetPitch(aFontInfo.fixedPitch() ? PITCH_FIXED : PITCH_VARIABLE);
+
+    FontWeight eWeight;
+    switch( aFontInfo.weight() )
+    {
+    case QFont::Thin: eWeight = WEIGHT_THIN; break;
+    case QFont::ExtraLight: eWeight =  WEIGHT_ULTRALIGHT; break;
+    case QFont::Light: eWeight = WEIGHT_LIGHT; break;
+    case QFont::Normal: eWeight = WEIGHT_NORMAL; break;
+    case QFont::Medium: eWeight = WEIGHT_MEDIUM; break;
+    case QFont::DemiBold: eWeight = WEIGHT_SEMIBOLD; break;
+    case QFont::Bold: eWeight = WEIGHT_BOLD; break;
+    case QFont::ExtraBold: eWeight = WEIGHT_ULTRABOLD; break;
+    case QFont::Black: eWeight = WEIGHT_BLACK; break;
+    }
+    aFA.SetWeight(eWeight);
+
+    SAL_INFO("vcl.qt5.font", toOUString(aFontInfo.family()) << " " << aFontInfo.weight() << " => " << (int) eWeight );
 
     return new Qt5FontFace(aFA, rFont.toString());
 }
diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx
index 7bed0a43aed6..372214956d73 100644
--- a/vcl/qt5/Qt5Graphics_GDI.cxx
+++ b/vcl/qt5/Qt5Graphics_GDI.cxx
@@ -207,7 +207,7 @@ void Qt5Graphics::drawRect(long nX, long nY, long nWidth, long nHeight)
     Qt5Painter aPainter(*this, true);
     if (SALCOLOR_NONE != m_aFillColor)
         aPainter.fillRect(nX, nY, nWidth, nHeight, aPainter.brush());
-    else
+    if (SALCOLOR_NONE != m_aLineColor)
         aPainter.drawRect(nX, nY, nWidth, nHeight);
     aPainter.update(nX, nY, nWidth, nHeight);
 }
@@ -248,9 +248,31 @@ void Qt5Graphics::drawPolygon(sal_uInt32 nPoints, const SalPoint* pPtAry)
     aPainter.update(aPolygon.boundingRect());
 }
 
-void Qt5Graphics::drawPolyPolygon(sal_uInt32 /*nPoly*/, const sal_uInt32* /*pPoints*/,
-                                  PCONSTSALPOINT* /*pPtAry*/)
+void Qt5Graphics::drawPolyPolygon(sal_uInt32 nPolyCount, const sal_uInt32* pPoints,
+                                  PCONSTSALPOINT* ppPtAry)
 {
+    // ignore invisible polygons
+    if (SALCOLOR_NONE == m_aFillColor && SALCOLOR_NONE == m_aLineColor)
+        return;
+
+    QPainterPath aPath;
+    for( sal_uInt32 nPoly = 0; nPoly < nPolyCount; nPoly++ )
+    {
+        const sal_uInt32 nPoints = pPoints[nPoly];
+        if( nPoints > 1 )
+        {
+            const SalPoint *pPtAry = ppPtAry[nPoly];
+            aPath.moveTo(pPtAry->mnX, pPtAry->mnY);
+            pPtAry++;
+            for( sal_uInt32 nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ )
+                aPath.lineTo(pPtAry->mnX, pPtAry->mnY);
+            aPath.closeSubpath();
+        }
+    }
+
+    Qt5Painter aPainter(*this, true);
+    aPainter.drawPath(aPath);
+    aPainter.update(aPath.boundingRect());
 }
 
 bool Qt5Graphics::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly, double fTransparency)
@@ -368,6 +390,7 @@ void Qt5Graphics::copyArea(long nDestX, long nDestY, long nSrcX, long nSrcY, lon
 
 void Qt5Graphics::copyBits(const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics)
 {
+
     if (rPosAry.mnSrcWidth <= 0 || rPosAry.mnSrcHeight <= 0 || rPosAry.mnDestWidth <= 0
         || rPosAry.mnDestHeight <= 0)
         return;
@@ -375,21 +398,30 @@ void Qt5Graphics::copyBits(const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics)
     assert(rPosAry.mnSrcWidth == rPosAry.mnDestWidth);
     assert(rPosAry.mnSrcHeight == rPosAry.mnDestHeight);
 
-    QImage aImage, *pImage = &aImage;
+    QImage aImage, *pImage;
+    int nSrcX, nSrcY;
     if (!pSrcGraphics || this == pSrcGraphics)
     {
         if (rPosAry.mnDestX == rPosAry.mnSrcX && rPosAry.mnDestY == rPosAry.mnSrcY)
             return;
+        pImage = static_cast<Qt5Graphics*>(this)->m_pQImage;
         aImage
             = pImage->copy(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight);
+        pImage = &aImage;
+        nSrcX = 0;
+        nSrcY = 0;
     }
     else
+    {
         pImage = static_cast<Qt5Graphics*>(pSrcGraphics)->m_pQImage;
+        nSrcX = rPosAry.mnSrcX;
+        nSrcY = rPosAry.mnSrcY;
+    }
 
     Qt5Painter aPainter(*this);
     aPainter.drawImage(
         QPoint(rPosAry.mnDestX, rPosAry.mnDestY), *pImage,
-        QRect(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight));
+        QRect(nSrcX, nSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight));
     aPainter.update(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight);
 }
 
@@ -399,14 +431,23 @@ void Qt5Graphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBit
         || rPosAry.mnDestHeight <= 0)
         return;
 
+    if (rPosAry.mnSrcWidth != rPosAry.mnDestWidth)
+        return;
+    if (rPosAry.mnSrcHeight != rPosAry.mnDestHeight)
+        return;
     assert(rPosAry.mnSrcWidth == rPosAry.mnDestWidth);
     assert(rPosAry.mnSrcHeight == rPosAry.mnDestHeight);
 
-    Qt5Painter aPainter(*this);
+    Qt5Bitmap aRGBABitmap;
+    if (rSalBitmap.GetBitCount() == 4)
+        aRGBABitmap.Create(rSalBitmap, 32);
 
-    const QImage* pImage = static_cast<const Qt5Bitmap*>(&rSalBitmap)->GetQImage();
+    const QImage* pImage = (rSalBitmap.GetBitCount() != 4)
+        ? static_cast<const Qt5Bitmap*>(&rSalBitmap)->GetQImage()
+        : aRGBABitmap.GetQImage();
     assert(pImage);
 
+    Qt5Painter aPainter(*this);
     aPainter.drawImage(
         QPoint(rPosAry.mnDestX, rPosAry.mnDestY), *pImage,
         QRect(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight));
@@ -422,6 +463,8 @@ void Qt5Graphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& /*rSalB
 
     assert(rPosAry.mnSrcWidth == rPosAry.mnDestWidth);
     assert(rPosAry.mnSrcHeight == rPosAry.mnDestHeight);
+
+    assert(0 && "Qt5Graphics::drawBitmap");
 }
 
 void Qt5Graphics::drawMask(const SalTwoRect& rPosAry, const SalBitmap& /*rSalBitmap*/,
@@ -433,6 +476,8 @@ void Qt5Graphics::drawMask(const SalTwoRect& rPosAry, const SalBitmap& /*rSalBit
 
     assert(rPosAry.mnSrcWidth == rPosAry.mnDestWidth);
     assert(rPosAry.mnSrcHeight == rPosAry.mnDestHeight);
+
+    assert(0 && "Qt5Graphics::drawMask");
 }
 
 SalBitmap* Qt5Graphics::getBitmap(long nX, long nY, long nWidth, long nHeight)
@@ -442,13 +487,35 @@ SalBitmap* Qt5Graphics::getBitmap(long nX, long nY, long nWidth, long nHeight)
 
 Color Qt5Graphics::getPixel(long nX, long nY) { return m_pQImage->pixel(nX, nY); }
 
-void Qt5Graphics::invert(long /*nX*/, long /*nY*/, long /*nWidth*/, long /*nHeight*/,
-                         SalInvert /*nFlags*/)
+void Qt5Graphics::invert(long nX, long nY, long nWidth, long nHeight, SalInvert nFlags)
 {
+    Qt5Painter aPainter(*this);
+    if (SalInvert::N50 & nFlags)
+    {
+        aPainter.setCompositionMode(QPainter::RasterOp_SourceXorDestination);
+        aPainter.setBrush(Qt::DiagCrossPattern);
+        aPainter.fillRect(nX, nY, nWidth, nHeight, aPainter.brush());
+    }
+    else
+    {
+        if (SalInvert::TrackFrame & nFlags)
+        {
+            aPainter.setCompositionMode(QPainter::RasterOp_SourceXorDestination);
+            aPainter.setPen(Qt::DashLine);
+            aPainter.drawRect(nX, nY, nWidth, nHeight);
+        }
+        else
+        {
+            aPainter.setCompositionMode(QPainter::RasterOp_SourceXorDestination);
+            aPainter.fillRect(nX, nY, nWidth, nHeight, Qt::white);
+        }
+    }
+    aPainter.update(nX, nY, nWidth, nHeight);
 }
 
 void Qt5Graphics::invert(sal_uInt32 /*nPoints*/, const SalPoint* /*pPtAry*/, SalInvert /*nFlags*/)
 {
+    assert(0 && "Qt5Graphics::invert 2");
 }
 
 bool Qt5Graphics::drawEPS(long /*nX*/, long /*nY*/, long /*nWidth*/, long /*nHeight*/,
@@ -469,13 +536,19 @@ bool Qt5Graphics::blendAlphaBitmap(const SalTwoRect&, const SalBitmap& /*rSrcBit
 static bool getAlphaImage(const SalBitmap& rSourceBitmap, const SalBitmap& rAlphaBitmap,
                           QImage& rAlphaImage)
 {
-    if (rAlphaBitmap.GetBitCount() != 8 && rAlphaBitmap.GetBitCount() != 1)
+    if ((rAlphaBitmap.GetBitCount() != 8 && rAlphaBitmap.GetBitCount() != 1))
     {
         SAL_WARN("vcl.gdi", "unsupported alpha depth case: " << rAlphaBitmap.GetBitCount());
         return false;
     }
 
-    const QImage* pBitmap = static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage();
+    Qt5Bitmap aRGBABitmap;
+    if (rSourceBitmap.GetBitCount() == 4)
+        aRGBABitmap.Create(rSourceBitmap, 32);
+
+    const QImage* pBitmap = (rSourceBitmap.GetBitCount() != 4)
+        ? static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage()
+        : aRGBABitmap.GetQImage();
     const QImage* pAlpha = static_cast<const Qt5Bitmap*>(&rAlphaBitmap)->GetQImage();
     rAlphaImage = pBitmap->convertToFormat(Qt5_DefaultFormat32);
 
@@ -499,7 +572,7 @@ static bool getAlphaImage(const SalBitmap& rSourceBitmap, const SalBitmap& rAlph
             {
                 if (x && !(x % 8))
                     ++alpha_line;
-                if (0 == (*alpha_line & (1 << (x % 8))))
+                if (0 != (*alpha_line & (1 << (7 - x % 8))))
                     image_line[3] = 0;
             }
         }
@@ -532,7 +605,13 @@ bool Qt5Graphics::drawTransformedBitmap(const basegfx::B2DPoint& rNull, const ba
         return false;
     else
     {
-        const QImage* pBitmap = static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage();
+        Qt5Bitmap aRGBABitmap;
+        if (rSourceBitmap.GetBitCount() == 4)
+            aRGBABitmap.Create(rSourceBitmap, 32);
+
+        const QImage* pBitmap = (rSourceBitmap.GetBitCount() != 4)
+            ? static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage()
+            : aRGBABitmap.GetQImage();
         aImage = pBitmap->convertToFormat(Qt5_DefaultFormat32);
     }
 
@@ -556,7 +635,7 @@ bool Qt5Graphics::drawAlphaRect(long nX, long nY, long nWidth, long nHeight,
     Qt5Painter aPainter(*this, true, nTransparency);
     if (SALCOLOR_NONE != m_aFillColor)
         aPainter.fillRect(nX, nY, nWidth, nHeight, aPainter.brush());
-    else
+    if (SALCOLOR_NONE != m_aLineColor)
         aPainter.drawRect(nX, nY, nWidth, nHeight);
     aPainter.update(nX, nY, nWidth, nHeight);
     return true;
diff --git a/vcl/qt5/Qt5Graphics_Text.cxx b/vcl/qt5/Qt5Graphics_Text.cxx
index 1d47f1c9249c..d66e85553fff 100644
--- a/vcl/qt5/Qt5Graphics_Text.cxx
+++ b/vcl/qt5/Qt5Graphics_Text.cxx
@@ -67,14 +67,15 @@ void Qt5Graphics::GetFontMetric(ImplFontMetricDataRef& rFMD, int nFallbackLevel)
 
     rFMD->ImplCalcLineSpacing(rHhea, rOS2, aRawFont.unitsPerEm());
 
+    rFMD->SetSlant( 0 );
     rFMD->SetWidth(aRawFont.averageCharWidth());
 
-    const QChar nKashidaCh[2] = { 0x06, 0x40 };
-    quint32 nKashidaGid = 0;
+    const QChar nKashidaCh = 0x0640;
+    int nNumGlyphs = 1;
+    quint32 nKashidaGid;
     QPointF aPoint;
-    int nNumGlyphs;
-    if (aRawFont.glyphIndexesForChars(nKashidaCh, 1, &nKashidaGid, &nNumGlyphs)
-        && aRawFont.advancesForGlyphIndexes(&nKashidaGid, &aPoint, 1))
+    if (aRawFont.glyphIndexesForChars(&nKashidaCh, nNumGlyphs, &nKashidaGid, &nNumGlyphs)
+            && aRawFont.advancesForGlyphIndexes(&nKashidaGid, &aPoint, nNumGlyphs))
         rFMD->SetMinKashida(lrint(aPoint.rx()));
 }
 
@@ -114,6 +115,7 @@ void Qt5Graphics::ClearDevFontCache() {}
 bool Qt5Graphics::AddTempDevFont(PhysicalFontCollection*, const OUString& /*rFileURL*/,
                                  const OUString& /*rFontName*/)
 {
+    assert(0 && "Qt5Graphics::AddTempDevFont");
     return false;
 }
 
@@ -130,11 +132,15 @@ const void* Qt5Graphics::GetEmbedFontData(const PhysicalFontFace*, long* /*pData
     return nullptr;
 }
 
-void Qt5Graphics::FreeEmbedFontData(const void* /*pData*/, long /*nDataLen*/) {}
+void Qt5Graphics::FreeEmbedFontData(const void* /*pData*/, long /*nDataLen*/)
+{
+    assert(0 && "Qt5Graphics::FreeEmbedFontData");
+}
 
 void Qt5Graphics::GetGlyphWidths(const PhysicalFontFace* /*pPFF*/, bool /*bVertical*/,
                                  std::vector<sal_Int32>& /*rWidths*/, Ucs2UIntMap& /*rUnicodeEnc*/)
 {
+    assert(0 && "Qt5Graphics::GetGlyphWidths");
 }
 
 bool Qt5Graphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& rRect)
@@ -148,16 +154,30 @@ bool Qt5Graphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& r
         return false;
 
     QRawFont aRawFont(QRawFont::fromFont( *pFont ));
-    rRect = toRectangle(aRawFont.boundingRect(rGlyph.maGlyphId).toAlignedRect());
+    rRect = toRectangle(aRawFont.boundingRect(rGlyph.maGlyphId).toRect());
     return true;
 }
 
-bool Qt5Graphics::GetGlyphOutline(const GlyphItem&, basegfx::B2DPolyPolygon&) { return false; }
+bool Qt5Graphics::GetGlyphOutline(const GlyphItem&, basegfx::B2DPolyPolygon&)
+{
+    return false;
+}
+
+class Qt5CommonSalLayout : public CommonSalLayout
+{
+public:
+    Qt5CommonSalLayout(LogicalFontInstance& rLFI): CommonSalLayout(rLFI) {}
+
+    void SetOrientation(int nOrientation)
+    {
+        mnOrientation = nOrientation;
+    }
+};
 
 std::unique_ptr<SalLayout> Qt5Graphics::GetTextLayout(ImplLayoutArgs&, int nFallbackLevel)
 {
     if (m_pTextStyle[nFallbackLevel])
-        return std::unique_ptr<SalLayout>(new CommonSalLayout(*m_pTextStyle[nFallbackLevel]));
+        return std::unique_ptr<SalLayout>(new Qt5CommonSalLayout(*m_pTextStyle[nFallbackLevel]));
     return std::unique_ptr<SalLayout>();
 }
 
@@ -170,6 +190,13 @@ void Qt5Graphics::DrawTextLayout(const CommonSalLayout &rLayout )
     QVector<quint32> glyphIndexes;
     QVector<QPointF> positions;
 
+    // prevent glyph rotation inside the SalLayout
+    // probably better to add a parameter to GetNextGlyphs?
+    Qt5CommonSalLayout *pQt5Layout = static_cast<Qt5CommonSalLayout*>(const_cast<CommonSalLayout*>(&rLayout));
+    int nOrientation = rLayout.GetOrientation();
+    if (nOrientation)
+        pQt5Layout->SetOrientation(0);
+
     Point aPos;
     const GlyphItem* pGlyph;
     int nStart = 0;
@@ -179,6 +206,9 @@ void Qt5Graphics::DrawTextLayout(const CommonSalLayout &rLayout )
         positions.push_back(QPointF(aPos.X(), aPos.Y()));
     }
 
+    if (nOrientation)
+        pQt5Layout->SetOrientation(nOrientation);
+
     QGlyphRun aGlyphRun;
     aGlyphRun.setPositions( positions );
     aGlyphRun.setGlyphIndexes( glyphIndexes );
@@ -187,6 +217,21 @@ void Qt5Graphics::DrawTextLayout(const CommonSalLayout &rLayout )
     Qt5Painter aPainter(*this);
     QColor aColor = QColor::fromRgb(QRgb(m_aTextColor));
     aPainter.setPen(aColor);
+
+    if (nOrientation)
+    {
+        // make text position the center of the rotation
+        // then rotate and move back
+        QRect window = aPainter.window();
+        window.moveTo(-positions[0].x(), -positions[0].y());
+        aPainter.setWindow(window);
+
+        QTransform p;
+        p.rotate(-static_cast<qreal>(nOrientation) / 10.0);
+        p.translate(-positions[0].x(), -positions[0].y());
+        aPainter.setTransform(p);
+    }
+
     aPainter.drawGlyphRun( QPointF(), aGlyphRun );
 }
 
diff --git a/vcl/source/font/fontcache.cxx b/vcl/source/font/fontcache.cxx
index e147cc68b30f..cf72a7bf76a5 100644
--- a/vcl/source/font/fontcache.cxx
+++ b/vcl/source/font/fontcache.cxx
@@ -48,7 +48,7 @@ bool ImplFontCache::IFSD_Equal::operator()(const FontSelectPattern& rA, const Fo
         return false;
 
     // check font face attributes
-    if( (rA.GetWeight()       != rB.GetWeight())
+    if( (rA.GetWeight()    != rB.GetWeight())
     ||  (rA.GetItalic()    != rB.GetItalic())
 //  ||  (rA.meFamily       != rB.meFamily) // TODO: remove this mostly obsolete member
     ||  (rA.GetPitch()     != rB.GetPitch()) )
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx
index c6465823a12c..453112df5369 100644
--- a/vcl/source/outdev/font.cxx
+++ b/vcl/source/outdev/font.cxx
@@ -167,7 +167,7 @@ bool OutputDevice::AddTempDevFont( const OUString& rFileURL, const OUString& rFo
 FontMetric OutputDevice::GetFontMetric() const
 {
     FontMetric aMetric;
-    if( mbNewFont && !ImplNewFont() )
+    if( !ImplNewFont() )
         return aMetric;
 
     LogicalFontInstance* pFontInstance = mpFontInstance;
@@ -230,10 +230,8 @@ bool OutputDevice::GetFontCharMap( FontCharMapRef& rxFontCharMap ) const
     if( !mpGraphics && !AcquireGraphics() )
         return false;
 
-    if( mbNewFont )
-        ImplNewFont();
-    if( mbInitFont )
-        InitFont();
+    ImplNewFont();
+    InitFont();
     if( !mpFontInstance )
         return false;
 
@@ -255,10 +253,8 @@ bool OutputDevice::GetFontCapabilities( vcl::FontCapabilities& rFontCapabilities
     if( !mpGraphics && !AcquireGraphics() )
         return false;
 
-    if( mbNewFont )
-        ImplNewFont();
-    if( mbInitFont )
-        InitFont();
+    ImplNewFont();
+    InitFont();
     if( !mpFontInstance )
         return false;
 
@@ -975,28 +971,25 @@ void OutputDevice::ImplInitFontList() const
 
 void OutputDevice::InitFont() const
 {
-    DBG_TESTSOLARMUTEX();
-
-    if (!mpFontInstance)
+    if (!mpFontInstance || !mbInitFont)
         return;
 
-    if ( mbInitFont )
-    {
-        // decide if antialiasing is appropriate
-        bool bNonAntialiased(GetAntialiasing() & AntialiasingFlags::DisableText);
-        FontSelectPattern aPattern(mpFontInstance->GetFontSelectPattern());
-        if (!utl::ConfigManager::IsFuzzing())
-        {
-            const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
-            bNonAntialiased |= bool(rStyleSettings.GetDisplayOptions() & DisplayOptions::AADisable);
-            bNonAntialiased |= (int(rStyleSettings.GetAntialiasingMinPixelHeight()) > aPattern.mnHeight);
-        }
-        aPattern.mbNonAntialiased = bNonAntialiased;
+    DBG_TESTSOLARMUTEX();
 
-        // select font in the device layers
-        mpGraphics->SetFont(&aPattern, 0);
-        mbInitFont = false;
+    // decide if antialiasing is appropriate
+    bool bNonAntialiased(GetAntialiasing() & AntialiasingFlags::DisableText);
+    FontSelectPattern aPattern(mpFontInstance->GetFontSelectPattern());
+    if (!utl::ConfigManager::IsFuzzing())
+    {
+        const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+        bNonAntialiased |= bool(rStyleSettings.GetDisplayOptions() & DisplayOptions::AADisable);
+        bNonAntialiased |= (int(rStyleSettings.GetAntialiasingMinPixelHeight()) > aPattern.mnHeight);
     }
+    aPattern.mbNonAntialiased = bNonAntialiased;
+
+    // select font in the device layers
+    mpGraphics->SetFont(&aPattern, 0);
+    mbInitFont = false;
 }
 
 bool OutputDevice::ImplNewFont() const
@@ -1035,29 +1028,28 @@ bool OutputDevice::ImplNewFont() const
             aSize.setHeight( 1 );
         else
             aSize.setHeight( (12*mnDPIY)/72 );
-        fExactHeight =  static_cast<float>(aSize.Height());
+        fExactHeight = static_cast<float>(aSize.Height());
     }
 
     // select the default width only when logical width is zero
     if( (0 == aSize.Width()) && (0 != maFont.GetFontSize().Width()) )
         aSize.setWidth( 1 );
 
-    // get font entry
+    // get new font entry
+    LogicalFontInstance* pFontInstance = mpFontCache->GetFontInstance( mpFontCollection, maFont, aSize, fExactHeight );
     LogicalFontInstance* pOldFontInstance = mpFontInstance;
-    mpFontInstance = mpFontCache->GetFontInstance( mpFontCollection, maFont, aSize, fExactHeight );
+    mpFontInstance = pFontInstance;
     if( pOldFontInstance )
         pOldFontInstance->Release();
-
-    LogicalFontInstance* pFontInstance = mpFontInstance;
-
     if (!pFontInstance)
     {
         SAL_WARN("vcl.gdi", "OutputDevice::ImplNewFont(): no LogicalFontInstance, no Font");
         return false;
     }
 
-    // mark when lower layers need to get involved
     mbNewFont = false;
+
+    // mark when lower layers need to get involved
     if( pFontInstance != pOldFontInstance )
         mbInitFont = true;
 
@@ -1100,14 +1092,13 @@ bool OutputDevice::ImplNewFont() const
     }
 
     // calculate text offset depending on TextAlignment
-    TextAlign eAlign = maFont.GetAlignment();
-    if ( eAlign == ALIGN_BASELINE )
+    switch (maFont.GetAlignment())
     {
+    case ALIGN_BASELINE:
         mnTextOffX = 0;
         mnTextOffY = 0;
-    }
-    else if ( eAlign == ALIGN_TOP )
-    {
+        break;
+    case ALIGN_TOP:
         mnTextOffX = 0;
         mnTextOffY = +pFontInstance->mxFontMetric->GetAscent() + mnEmphasisAscent;
         if ( pFontInstance->mnOrientation )
@@ -1115,9 +1106,8 @@ bool OutputDevice::ImplNewFont() const
             Point aOriginPt(0, 0);
             aOriginPt.RotateAround( mnTextOffX, mnTextOffY, pFontInstance->mnOrientation );
         }
-    }
-    else // eAlign == ALIGN_BOTTOM
-    {
+        break;
+    case ALIGN_BOTTOM:
         mnTextOffX = 0;
         mnTextOffY = -pFontInstance->mxFontMetric->GetDescent() + mnEmphasisDescent;
         if ( pFontInstance->mnOrientation )
@@ -1125,6 +1115,10 @@ bool OutputDevice::ImplNewFont() const
             Point aOriginPt(0, 0);
             aOriginPt.RotateAround( mnTextOffX, mnTextOffY, pFontInstance->mnOrientation );
         }
+        break;
+    case TextAlign_FORCE_EQUAL_SIZE:
+        assert( 0 && "TextAlign_FORCE_EQUAL_SIZE not implemented for new fonts" );
+        break;
     }
 
     mbTextLines     = ((maFont.GetUnderline() != LINESTYLE_NONE) && (maFont.GetUnderline() != LINESTYLE_DONTKNOW)) ||
@@ -1410,7 +1404,7 @@ std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_pt
 
 long OutputDevice::GetMinKashida() const
 {
-    if( mbNewFont && !ImplNewFont() )
+    if( !ImplNewFont() )
         return 0;
 
     return ImplDevicePixelToLogicWidth( mpFontInstance->mxFontMetric->GetMinKashida() );
commit d5c8d66630a18a2622b15d7d44e00f61eaf17763
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Apr 13 09:04:56 2018 +0200

    Header comment
    
    Change-Id: I641da593df5a1fa2964b3e01f5d323edf73c6721

diff --git a/vcl/inc/fontselect.hxx b/vcl/inc/fontselect.hxx
index 389077270758..e15cd62291d4 100644
--- a/vcl/inc/fontselect.hxx
+++ b/vcl/inc/fontselect.hxx
@@ -58,7 +58,7 @@ public:
     int             mnWidth;                    // width of font in pixel units
     int             mnHeight;                   // height of font in pixel units
     float           mfExactHeight;              // requested height (in pixels with subpixel details)
-    int             mnOrientation;              // text orientation in 3600 system
+    int             mnOrientation;              // text orientation in 1/10 degree (0-3600)
     LanguageType    meLanguage;                 // text language
     bool            mbVertical;                 // vertical mode of requested font
     bool            mbNonAntialiased;           // true if antialiasing is disabled
commit 96a6a45122e83caebf0d79da82633302ea158fde
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Mar 12 09:56:18 2018 +0100

    Qt5 fix font drawing
    
    The main problem was the memory management of the harfbuzz memory
    blob. Now we copy the font data tables into the blob, as the
    QByteArray memory will be freed at the end of the function.
    
    Change-Id: If5a5a4b1a235e66ba472b28a156e16be1b82bf2e

diff --git a/vcl/qt5/Qt5Font.cxx b/vcl/qt5/Qt5Font.cxx
index 51e87e8a1958..74918a70f008 100644
--- a/vcl/qt5/Qt5Font.cxx
+++ b/vcl/qt5/Qt5Font.cxx
@@ -41,8 +41,8 @@ static hb_blob_t* getFontTable(hb_face_t*, hb_tag_t nTableTag, void* pUserData)
 
     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);
+        pBlob = hb_blob_create(aTable.data(), nLength,
+                               HB_MEMORY_MODE_DUPLICATE, nullptr, nullptr);
     return pBlob;
 }
 
diff --git a/vcl/qt5/Qt5FontFace.cxx b/vcl/qt5/Qt5FontFace.cxx
index 0cd071385aaa..b7a0f0b12f9e 100644
--- a/vcl/qt5/Qt5FontFace.cxx
+++ b/vcl/qt5/Qt5FontFace.cxx
@@ -28,6 +28,7 @@
 #include <PhysicalFontCollection.hxx>
 
 #include <QtGui/QFont>
+#include <QtGui/QFontInfo>
 #include <QtGui/QRawFont>
 
 using namespace vcl;
diff --git a/vcl/qt5/Qt5Graphics_Text.cxx b/vcl/qt5/Qt5Graphics_Text.cxx
index 08c53bfd323b..1d47f1c9249c 100644
--- a/vcl/qt5/Qt5Graphics_Text.cxx
+++ b/vcl/qt5/Qt5Graphics_Text.cxx
@@ -137,7 +137,20 @@ void Qt5Graphics::GetGlyphWidths(const PhysicalFontFace* /*pPFF*/, bool /*bVerti
 {
 }
 
-bool Qt5Graphics::GetGlyphBoundRect(const GlyphItem&, tools::Rectangle&) { return false; }
+bool Qt5Graphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& rRect)
+{
+    const int nLevel = rGlyph.mnFallbackLevel;
+    if( nLevel >= MAX_FALLBACK )
+        return false;
+
+    Qt5Font* pFont = m_pTextStyle[ nLevel ];
+    if( !pFont )
+        return false;
+
+    QRawFont aRawFont(QRawFont::fromFont( *pFont ));
+    rRect = toRectangle(aRawFont.boundingRect(rGlyph.maGlyphId).toAlignedRect());
+    return true;
+}
 
 bool Qt5Graphics::GetGlyphOutline(const GlyphItem&, basegfx::B2DPolyPolygon&) { return false; }
 
diff --git a/vcl/qt5/Qt5Tools.hxx b/vcl/qt5/Qt5Tools.hxx
index bfd604993fd0..c7b47014beb0 100644
--- a/vcl/qt5/Qt5Tools.hxx
+++ b/vcl/qt5/Qt5Tools.hxx
@@ -46,6 +46,11 @@ inline QRect toQRect(const tools::Rectangle& rRect)
     return QRect(rRect.Left(), rRect.Top(), rRect.GetWidth(), rRect.GetHeight());
 }
 
+inline tools::Rectangle toRectangle(const QRect& rRect)
+{
+    return tools::Rectangle(rRect.left(), rRect.top(), rRect.width(), rRect.height());
+}
+
 inline QSize toQSize(const Size& rSize) { return QSize(rSize.Width(), rSize.Height()); }
 
 inline Size toSize(const QSize& rSize) { return Size(rSize.width(), rSize.height()); }
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index aa59117a166a..e78cedc21724 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -271,8 +271,6 @@ bool CommonSalLayout::HasVerticalAlternate(sal_UCS4 aChar, sal_UCS4 aVariationSe
 
 bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
 {
-    hb_face_t* pHbFace = hb_font_get_face(mpFont->GetHbFont());
-
     int nGlyphCapacity = 2 * (rArgs.mnEndCharPos - rArgs.mnMinCharPos);
     Reserve(nGlyphCapacity);
 
@@ -312,6 +310,8 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
     mpFont->GetScale(&nXScale, &nYScale);
 
     Point aCurrPos(0, 0);
+    hb_font_t *pHbFont = mpFont->GetHbFont();
+    hb_face_t *pHbFace = hb_font_get_face(pHbFont);
     while (true)
     {
         int nBidiMinRunPos, nBidiEndRunPos;
@@ -400,7 +400,6 @@ 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);
commit bd946ca575a2901b3f4e33073d8bd6305fec213b
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 9efe20d0682e02e8f40956c0073ea011bba883a7
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 da1d1723a7df..505a1cd21a8d 100644
--- a/vcl/unx/generic/app/saldisp.cxx
+++ b/vcl/unx/generic/app/saldisp.cxx
@@ -1495,6 +1495,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 f8a42da5cd5d129cb98264643446641ae8be4095
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 8ed96f6a1821f4d3a8f0efe6d858abf77077a187
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 ed3d849aa3f4..08c53bfd323b 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 17f848f49f14e3e147aa3caa3c613bef7f44a4f7
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 7eb734195756..dc09bc017307 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>
@@ -182,6 +183,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 000131744c15dc5ebbd95dc79f88afe36335f976
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 b6212ba959a4..f4e03fb728a2 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -756,22 +756,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 d470625ee80d..99469eb8755f 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:

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list