[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.2' - 10 commits - framework/Library_fwk.mk framework/source include/LibreOfficeKit include/vcl libreofficekit/qa libreofficekit/source sd/source sfx2/source vcl/inc vcl/source

Michael Meeks (via logerrit) logerrit at kemper.freedesktop.org
Tue Sep 24 13:00:06 UTC 2019


 framework/Library_fwk.mk                                    |    2 
 framework/source/uiconfiguration/ImageArrayData.cxx         |   91 -------
 framework/source/uiconfiguration/ImageList.cxx              |  149 ++++--------
 framework/source/uiconfiguration/ImageList.hxx              |   24 +
 framework/source/uiconfiguration/ImplImageList.cxx          |   71 -----
 framework/source/uiconfiguration/image.h                    |   67 -----
 framework/source/uiconfiguration/imagemanagerimpl.cxx       |    2 
 include/LibreOfficeKit/LibreOfficeKit.hxx                   |    2 
 include/vcl/ImageTree.hxx                                   |    6 
 include/vcl/graph.hxx                                       |    2 
 include/vcl/image.hxx                                       |    3 
 libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx |   15 -
 libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx |    2 
 libreofficekit/qa/gtktiledviewer/gtv-application.cxx        |    5 
 libreofficekit/qa/tilebench/tilebench.cxx                   |    2 
 libreofficekit/source/gtk/lokdocview.cxx                    |   63 +++++
 sd/source/ui/controller/slidelayoutcontroller.cxx           |   11 
 sd/source/ui/sidebar/LayoutMenu.cxx                         |   10 
 sfx2/source/sidebar/Tools.cxx                               |    9 
 vcl/inc/image.h                                             |   26 ++
 vcl/inc/implimagetree.hxx                                   |   15 -
 vcl/source/control/fixed.cxx                                |    3 
 vcl/source/gdi/graph.cxx                                    |   13 +
 vcl/source/helper/commandinfoprovider.cxx                   |   23 -
 vcl/source/image/Image.cxx                                  |  133 ++++------
 vcl/source/image/ImageTree.cxx                              |   10 
 vcl/source/image/ImplImage.cxx                              |  120 +++++++++
 vcl/source/image/ImplImageTree.cxx                          |   37 ++
 vcl/source/window/builder.cxx                               |    8 
 vcl/source/window/msgbox.cxx                                |   11 
 vcl/source/window/paint.cxx                                 |   11 
 vcl/source/window/winproc.cxx                               |    6 
 32 files changed, 479 insertions(+), 473 deletions(-)

New commits:
commit ad747625c821232790a4c435d4efe8629f849294
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Mon Nov 26 16:59:42 2018 +0000
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Tue Sep 24 13:58:53 2019 +0100

    Use lazy-loading stock Image to simplify framework image lists.
    
    Project stock names through XGraphic via origin URL.
    
    (cherry picked from commit 77b88eebaadebb626108172e4f2de36c60960051)
    
    Change-Id: Ib445694f7c142a163ef7e7bc0beea39b88b99e14

diff --git a/framework/source/uiconfiguration/ImageList.cxx b/framework/source/uiconfiguration/ImageList.cxx
index 100e152b17fc..93b89e71dc05 100644
--- a/framework/source/uiconfiguration/ImageList.cxx
+++ b/framework/source/uiconfiguration/ImageList.cxx
@@ -44,9 +44,7 @@ ImageList::ImageList(const std::vector< OUString >& rNameVector,
 
     maPrefix = rPrefix;
     for( size_t i = 0; i < rNameVector.size(); ++i )
-    {
-        ImplAddImage( rNameVector[ i ], static_cast< sal_uInt16 >( i ) + 1, BitmapEx() );
-    }
+        ImplAddImage( rPrefix, rNameVector[ i ], static_cast< sal_uInt16 >( i ) + 1, Image() );
 }
 
 // FIXME: Rather a performance hazard
@@ -57,15 +55,7 @@ BitmapEx ImageList::GetAsHorizontalStrip() const
         return BitmapEx();
     Size aSize( maImageSize.Width() * nCount, maImageSize.Height() );
 
-    // Load any stragglers
-    for (sal_uInt16 nIdx = 0; nIdx < nCount; nIdx++)
-    {
-        ImageAryData *pData = maImages[ nIdx ].get();
-        if( pData->IsLoadable() )
-            ImplLoad(*pData);
-    }
-
-    BitmapEx aTempl = maImages[ 0 ]->maBitmapEx;
+    BitmapEx aTempl = maImages[ 0 ]->maImage.GetBitmapEx();
     BitmapEx aResult( aTempl, Point(), aSize );
 
     tools::Rectangle aSrcRect( Point( 0, 0 ), maImageSize );
@@ -74,7 +64,8 @@ BitmapEx ImageList::GetAsHorizontalStrip() const
         tools::Rectangle aDestRect( Point( nIdx * maImageSize.Width(), 0 ),
                              maImageSize );
         ImageAryData *pData = maImages[ nIdx ].get();
-        aResult.CopyPixel( aDestRect, aSrcRect, &pData->maBitmapEx);
+        BitmapEx aTmp = pData->maImage.GetBitmapEx();
+        aResult.CopyPixel( aDestRect, aSrcRect, &aTmp );
     }
 
     return aResult;
@@ -101,7 +92,7 @@ void ImageList::InsertFromHorizontalStrip( const BitmapEx &rBitmapEx,
     for (sal_uInt16 nIdx = 0; nIdx < nItems; nIdx++)
     {
         BitmapEx aBitmap( rBitmapEx, Point( nIdx * aSize.Width(), 0 ), aSize );
-        ImplAddImage( rNameVector[ nIdx ], nIdx + 1, aBitmap );
+        ImplAddImage( maPrefix, rNameVector[ nIdx ], nIdx + 1, Image( aBitmap ) );
     }
 }
 
@@ -117,8 +108,7 @@ void ImageList::AddImage( const OUString& rImageName, const Image& rImage )
 {
     SAL_WARN_IF( GetImagePos( rImageName ) != IMAGELIST_IMAGE_NOTFOUND, "vcl", "ImageList::AddImage() - ImageName already exists" );
 
-    ImplAddImage( rImageName, GetImageCount() + 1,
-                          rImage.GetBitmapEx() );
+    ImplAddImage( maPrefix, rImageName, GetImageCount() + 1, rImage );
 }
 
 void ImageList::ReplaceImage( const OUString& rImageName, const Image& rImage )
@@ -127,10 +117,10 @@ void ImageList::ReplaceImage( const OUString& rImageName, const Image& rImage )
 
     if( nId )
     {
-        //Just replace the bitmap rather than doing RemoveImage / AddImage
-        //which breaks index-based iteration.
+        // Just replace the bitmap rather than doing RemoveImage / AddImage
+        // which breaks index-based iteration.
         ImageAryData *pImg = maNameHash[ rImageName ];
-        pImg->maBitmapEx = rImage.GetBitmapEx();
+        pImg->maImage = rImage;
     }
 }
 
@@ -151,10 +141,7 @@ Image ImageList::GetImage( const OUString& rImageName ) const
     auto it = maNameHash.find( rImageName );
     if (it == maNameHash.end())
         return Image();
-    ImageAryData *pImg = it->second;
-    if( pImg->IsLoadable() )
-        ImplLoad( *pImg );
-    return Image( pImg->maBitmapEx );
+    return it->second->maImage;
 }
 
 sal_uInt16 ImageList::GetImageCount() const
@@ -200,10 +187,14 @@ void ImageList::GetImageNames( std::vector< OUString >& rNames ) const
     }
 }
 
-void ImageList::ImplAddImage( const OUString &aName,
-                              sal_uInt16 nId, const BitmapEx &aBitmapEx )
+void ImageList::ImplAddImage( const OUString &aPrefix, const OUString &aName,
+                              sal_uInt16 nId, const Image &aImage )
 {
-    ImageAryData *pImg = new ImageAryData{ aName, nId, aBitmapEx };
+    Image aInsert = aImage;
+    if (!aInsert)
+        aInsert = Image( "private:graphicrepository/" + aPrefix + aName );
+
+    ImageAryData *pImg = new ImageAryData{ aName, nId, aInsert };
     maImages.emplace_back( pImg );
     if( !aName.isEmpty() )
         maNameHash [ aName ] = pImg;
@@ -217,29 +208,4 @@ void ImageList::ImplRemoveImage( sal_uInt16 nPos )
     maImages.erase( maImages.begin() + nPos );
 }
 
-void ImageList::ImplLoad(ImageAryData& rImageData) const
-{
-    OUString aIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
-
-    OUString aFileName = maPrefix + rImageData.maName;
-
-    bool bSuccess = ImageTree::get().loadImage(aFileName, aIconTheme, rImageData.maBitmapEx, true);
-
-    /* If the uno command has parameters, passed in from a toolbar,
-     * recover from failure by removing the parameters from the file name
-     */
-    if (!bSuccess && aFileName.indexOf("%3f") > 0)
-    {
-        sal_Int32 nStart = aFileName.indexOf("%3f");
-        sal_Int32 nEnd = aFileName.lastIndexOf(".");
-
-        aFileName = aFileName.replaceAt(nStart, nEnd - nStart, "");
-        bSuccess = ImageTree::get().loadImage(aFileName, aIconTheme, rImageData.maBitmapEx, true);
-    }
-
-    SAL_WARN_IF(!bSuccess, "fwk.uiconfiguration", "Failed to load image '" << aFileName
-              << "' from icon theme '" << aIconTheme << "'");
-}
-
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/uiconfiguration/ImageList.hxx b/framework/source/uiconfiguration/ImageList.hxx
index f610692fb672..7f72c980fdb3 100644
--- a/framework/source/uiconfiguration/ImageList.hxx
+++ b/framework/source/uiconfiguration/ImageList.hxx
@@ -20,18 +20,16 @@
 #ifndef FRAMEWORK_SOURCE_UICONFIGURATION_IMAGELIST_HXX
 #define FRAMEWORK_SOURCE_UICONFIGURATION_IMAGELIST_HXX
 
-#include <vcl/bitmapex.hxx>
+#include <vcl/image.hxx>
 #include <unordered_map>
 #include <vector>
 
 // Images identified by either name, or by id
 struct ImageAryData
 {
-    OUString                maName;
-    sal_uInt16              mnId;
-    BitmapEx                maBitmapEx;
-
-    bool IsLoadable() { return maBitmapEx.IsEmpty() && !maName.isEmpty(); }
+    OUString    maName;
+    sal_uInt16  mnId;
+    Image       maImage;
 };
 
 class ImageList
@@ -69,7 +67,7 @@ private:
     Size                   maImageSize;
 
     sal_uInt16  ImplGetImageId( const OUString& rImageName ) const;
-    void ImplAddImage( const OUString &aName, sal_uInt16 nId, const BitmapEx &aBitmapEx );
+    void ImplAddImage( const OUString &aPrefix, const OUString &aName, sal_uInt16 nId, const Image &aImage );
     void ImplRemoveImage( sal_uInt16 nPos );
     void ImplLoad(ImageAryData&) const;
 };
diff --git a/framework/source/uiconfiguration/imagemanagerimpl.cxx b/framework/source/uiconfiguration/imagemanagerimpl.cxx
index 650d44e2a1e4..5695de44dca5 100644
--- a/framework/source/uiconfiguration/imagemanagerimpl.cxx
+++ b/framework/source/uiconfiguration/imagemanagerimpl.cxx
@@ -713,7 +713,7 @@ namespace
 {
     css::uno::Reference< css::graphic::XGraphic > GetXGraphic(const Image &rImage)
     {
-        return Graphic(rImage.GetBitmapEx()).GetXGraphic();
+        return Graphic(rImage).GetXGraphic();
     }
 }
 
diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx
index 3b91a3269478..cc8df96fc68c 100644
--- a/include/vcl/graph.hxx
+++ b/include/vcl/graph.hxx
@@ -102,6 +102,7 @@ public:
     bool            getSnapHorVerLines() const { return mbSnapHorVerLines; }
 };
 
+class Image;
 class VCL_DLLPUBLIC Graphic
 {
 private:
@@ -119,6 +120,7 @@ public:
                     Graphic( const Graphic& rGraphic );
                     Graphic( Graphic&& rGraphic );
                     Graphic( const Bitmap& rBmp );
+                    Graphic( const Image& rImage );
                     Graphic( const BitmapEx& rBmpEx );
                     Graphic( const VectorGraphicDataPtr& rVectorGraphicDataPtr );
                     Graphic( const Animation& rAnimation );
diff --git a/include/vcl/image.hxx b/include/vcl/image.hxx
index 526243bcf382..862f1806296c 100644
--- a/include/vcl/image.hxx
+++ b/include/vcl/image.hxx
@@ -52,7 +52,6 @@ namespace vcl
 class SAL_WARN_UNUSED VCL_DLLPUBLIC Image
 {
     friend class ::OutputDevice;
-
 public:
                     Image();
                     explicit Image( const BitmapEx& rBitmapEx );
@@ -67,6 +66,8 @@ public:
     bool            operator==( const Image& rImage ) const;
     bool            operator!=( const Image& rImage ) const { return !(Image::operator==( rImage )); }
 
+    SAL_DLLPRIVATE  OUString GetStock() const;
+
     void Draw(OutputDevice* pOutDev, const Point& rPos, DrawImageFlags nStyle, const Size* pSize = nullptr);
 
 private:
diff --git a/sfx2/source/sidebar/Tools.cxx b/sfx2/source/sidebar/Tools.cxx
index 0f0f596f936d..cebfc93013d9 100644
--- a/sfx2/source/sidebar/Tools.cxx
+++ b/sfx2/source/sidebar/Tools.cxx
@@ -53,14 +53,13 @@ Image Tools::GetImage (
 {
     if (rsURL.getLength() > 0)
     {
+        OUString sPath;
+
         if (rsURL.startsWith(".uno:"))
-        {
             return vcl::CommandInfoProvider::GetImageForCommand(rsURL, rxFrame);
-        }
-        else
-        {
+
+        else if (rsURL.startsWith("private:graphicrepository/", &sPath))
             return Image(rsURL);
-        }
     }
     return Image();
 }
diff --git a/vcl/inc/image.h b/vcl/inc/image.h
index c9fb5393191a..5048a850aade 100644
--- a/vcl/inc/image.h
+++ b/vcl/inc/image.h
@@ -42,6 +42,11 @@ struct ImplImage
 
     bool isStock() const { return maStockName.getLength() > 0; }
 
+    OUString getStock() const
+    {
+        return maStockName;
+    }
+
     /// get size in co-ordinates not scaled for HiDPI
     Size getSizePixel();
     /// Legacy - the original bitmap
diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx
index 0b2c043572db..9a9cfea8502f 100644
--- a/vcl/source/gdi/graph.cxx
+++ b/vcl/source/gdi/graph.cxx
@@ -21,6 +21,7 @@
 #include <vcl/outdev.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/graph.hxx>
+#include <vcl/image.hxx>
 #include <vcl/metaact.hxx>
 #include <impgraph.hxx>
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
@@ -33,6 +34,7 @@
 #include <graphic/UnoGraphic.hxx>
 #include <vcl/GraphicExternalLink.hxx>
 
+#include <image.h>
 
 using namespace ::com::sun::star;
 
@@ -216,6 +218,17 @@ Graphic::Graphic(const BitmapEx& rBmpEx)
 {
 }
 
+// We use XGraphic for passing toolbar images across app UNO aps
+// and we need to be able to see and preserve 'stock' images too.
+Graphic::Graphic(const Image& rImage)
+    // FIXME: should really defer the BitmapEx load.
+    : mxImpGraphic(new ImpGraphic(rImage.GetBitmapEx()))
+{
+    OUString aStock = rImage.GetStock();
+    if (aStock.getLength())
+        mxImpGraphic->setOriginURL("private:graphicrepository/" + aStock);
+}
+
 Graphic::Graphic(const VectorGraphicDataPtr& rVectorGraphicDataPtr)
     : mxImpGraphic(vcl::graphic::Manager::get().newInstance(rVectorGraphicDataPtr))
 {
diff --git a/vcl/source/helper/commandinfoprovider.cxx b/vcl/source/helper/commandinfoprovider.cxx
index ee9196c6411e..80bc04f876a5 100644
--- a/vcl/source/helper/commandinfoprovider.cxx
+++ b/vcl/source/helper/commandinfoprovider.cxx
@@ -295,13 +295,13 @@ OUString GetRealCommandForCommand(const OUString& rCommandName,
     return GetCommandProperty("TargetURL", rCommandName, rsModuleName);
 }
 
-static BitmapEx GetBitmapForCommand(const OUString& rsCommandName,
-                             const Reference<frame::XFrame>& rxFrame,
-                             vcl::ImageType eImageType)
+static Reference<graphic::XGraphic> GetXGraphicForCommand(const OUString& rsCommandName,
+                                                          const Reference<frame::XFrame>& rxFrame,
+                                                          vcl::ImageType eImageType)
 {
 
     if (rsCommandName.isEmpty())
-        return BitmapEx();
+        return nullptr;
 
     sal_Int16 nImageType(ui::ImageType::COLOR_NORMAL | ui::ImageType::SIZE_DEFAULT);
 
@@ -324,11 +324,7 @@ static BitmapEx GetBitmapForCommand(const OUString& rsCommandName,
 
             aGraphicSeq = xDocImgMgr->getImages( nImageType, aImageCmdSeq );
             Reference<graphic::XGraphic> xGraphic = aGraphicSeq[0];
-            const Graphic aGraphic(xGraphic);
-            BitmapEx aBitmap(aGraphic.GetBitmapEx());
-
-            if (!!aBitmap)
-                return aBitmap;
+            return xGraphic;
         }
     }
     catch (Exception&)
@@ -347,23 +343,20 @@ static BitmapEx GetBitmapForCommand(const OUString& rsCommandName,
         aGraphicSeq = xModuleImageManager->getImages(nImageType, aImageCmdSeq);
 
         Reference<graphic::XGraphic> xGraphic(aGraphicSeq[0]);
-
-        const Graphic aGraphic(xGraphic);
-
-        return aGraphic.GetBitmapEx();
+        return xGraphic;
     }
     catch (Exception&)
     {
     }
 
-    return BitmapEx();
+    return nullptr;
 }
 
 Image GetImageForCommand(const OUString& rsCommandName,
                          const Reference<frame::XFrame>& rxFrame,
                          vcl::ImageType eImageType)
 {
-    return Image(GetBitmapForCommand(rsCommandName, rxFrame, eImageType));
+    return Image(GetXGraphicForCommand(rsCommandName, rxFrame, eImageType));
 }
 
 sal_Int32 GetPropertiesForCommand (
diff --git a/vcl/source/image/Image.cxx b/vcl/source/image/Image.cxx
index ecb514c5bbac..218f2f8512fc 100644
--- a/vcl/source/image/Image.cxx
+++ b/vcl/source/image/Image.cxx
@@ -49,24 +49,28 @@ Image::Image(const BitmapEx& rBitmapEx)
 
 Image::Image(const css::uno::Reference< css::graphic::XGraphic >& rxGraphic)
 {
-    const Graphic aGraphic(rxGraphic);
-    ImplInit(aGraphic.GetBitmapEx());
+    if (rxGraphic.is())
+    {
+        const Graphic aGraphic(rxGraphic);
+
+        OUString aPath;
+        if (aGraphic.getOriginURL().startsWith("private:graphicrepository/", &aPath))
+            mpImplData = std::make_shared<ImplImage>(aPath);
+        else
+            ImplInit(aGraphic.GetBitmapEx());
+    }
 }
 
 Image::Image(const OUString & rFileUrl)
 {
-    sal_Int32 nIndex = 0;
-    if (rFileUrl.getToken( 0, '/', nIndex ) == "private:graphicrepository")
-    {
-        mpImplData.reset(new ImplImage(rFileUrl.copy(nIndex)));
-    }
+    OUString sImageName;
+    if (rFileUrl.startsWith("private:graphicrepository/", &sImageName))
+        mpImplData = std::make_shared<ImplImage>(sImageName);
     else
     {
         Graphic aGraphic;
         if (ERRCODE_NONE == GraphicFilter::LoadGraphic(rFileUrl, IMP_PNG, aGraphic))
-        {
             ImplInit(aGraphic.GetBitmapEx());
-        }
     }
 }
 
@@ -76,6 +80,13 @@ void Image::ImplInit(const BitmapEx& rBitmapEx)
         mpImplData.reset(new ImplImage(rBitmapEx));
 }
 
+OUString Image::GetStock() const
+{
+    if (mpImplData)
+        return mpImplData->getStock();
+    return OUString();
+}
+
 Size Image::GetSizePixel() const
 {
     if (mpImplData)
diff --git a/vcl/source/image/ImplImage.cxx b/vcl/source/image/ImplImage.cxx
index 95d605e47173..dc5f12ab8b59 100644
--- a/vcl/source/image/ImplImage.cxx
+++ b/vcl/source/image/ImplImage.cxx
@@ -53,13 +53,37 @@ ImplImage::ImplImage(const OUString &aStockName)
 bool ImplImage::loadStockAtScale(double fScale, BitmapEx &rBitmapEx)
 {
     BitmapEx aBitmapEx;
+
+    ImageLoadFlags eScalingFlags = ImageLoadFlags::NONE;
+    sal_Int32 nScalePercentage = -1;
+
+    if (comphelper::LibreOfficeKit::isActive()) // scale at the surface
+    {
+        nScalePercentage = fScale * 100.0;
+        eScalingFlags = ImageLoadFlags::IgnoreScalingFactor;
+    }
+
     OUString aIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
     if (!ImageTree::get().loadImage(maStockName, aIconTheme, aBitmapEx, true,
-                                    fScale * 100.0,
-                                    ImageLoadFlags::IgnoreScalingFactor))
+                                    nScalePercentage, eScalingFlags))
     {
-        SAL_WARN("vcl", "Failed to load scaled image from " << maStockName << " at " << fScale);
-        return false;
+        /* If the uno command has parameters, passed in from a toolbar,
+         * recover from failure by removing the parameters from the file name
+         */
+        if (maStockName.indexOf("%3f") > 0)
+        {
+            sal_Int32 nStart = maStockName.indexOf("%3f");
+            sal_Int32 nEnd = maStockName.lastIndexOf(".");
+
+            OUString aFileName = maStockName.replaceAt(nStart, nEnd - nStart, "");
+            if (!ImageTree::get().loadImage(aFileName, aIconTheme, aBitmapEx, true,
+                                            nScalePercentage, eScalingFlags))
+            {
+                SAL_WARN("vcl", "Failed to load scaled image from " << maStockName <<
+                         " and " << aFileName << " at " << fScale);
+                return false;
+            }
+        }
     }
     rBitmapEx = aBitmapEx;
     return true;
@@ -123,7 +147,7 @@ BitmapEx ImplImage::getBitmapExForHiDPI(bool bDisabled)
         // FIXME: DPI scaling should be tied to the outdev really ...
         double fScale = comphelper::LibreOfficeKit::getDPIScale();
         Size aTarget(maSizePixel.Width()*fScale,
-                         maSizePixel.Height()*fScale);
+                     maSizePixel.Height()*fScale);
         if (maBitmapEx.GetSizePixel() != aTarget)
             loadStockAtScale(fScale, maBitmapEx);
     }
commit aa201ce2fc11a4ecd5dc2ac55c35db737e01275a
Author:     Noel Grandin <noel.grandin at collabora.co.uk>
AuthorDate: Fri Jul 19 16:31:37 2019 +0200
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Tue Sep 24 13:58:52 2019 +0100

    simplify ImageList
    
    we don't need an Impl pattern here
    
    Change-Id: I93d0c5904a3aee8844987c7e36c19319d071d2f4
    Reviewed-on: https://gerrit.libreoffice.org/75960
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>

diff --git a/framework/Library_fwk.mk b/framework/Library_fwk.mk
index 9057aaa6048a..6d1f124f2f5a 100644
--- a/framework/Library_fwk.mk
+++ b/framework/Library_fwk.mk
@@ -113,9 +113,7 @@ $(eval $(call gb_Library_add_exception_objects,fwk,\
     framework/source/services/taskcreatorsrv \
     framework/source/services/urltransformer \
     framework/source/uiconfiguration/CommandImageResolver \
-    framework/source/uiconfiguration/ImageArrayData \
     framework/source/uiconfiguration/ImageList \
-    framework/source/uiconfiguration/ImplImageList \
     framework/source/uiconfiguration/globalsettings \
     framework/source/uiconfiguration/graphicnameaccess \
     framework/source/uiconfiguration/imagemanager \
diff --git a/framework/source/uiconfiguration/ImageArrayData.cxx b/framework/source/uiconfiguration/ImageArrayData.cxx
deleted file mode 100644
index 570d2846ff77..000000000000
--- a/framework/source/uiconfiguration/ImageArrayData.cxx
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*- 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 <vcl/outdev.hxx>
-#include <vcl/bitmapex.hxx>
-#include <vcl/alpha.hxx>
-#include <vcl/window.hxx>
-#include <vcl/bitmapaccess.hxx>
-#include <vcl/virdev.hxx>
-#include <vcl/image.hxx>
-#include <vcl/settings.hxx>
-#include <vcl/svapp.hxx>
-#include <vcl/ImageTree.hxx>
-
-#include "image.h"
-#include <memory>
-#include <sal/log.hxx>
-
-#if OSL_DEBUG_LEVEL > 0
-#include <rtl/strbuf.hxx>
-#endif
-
-ImageAryData::ImageAryData( const ImageAryData& rData ) :
-    maName( rData.maName ),
-    mnId( rData.mnId ),
-    maBitmapEx( rData.maBitmapEx )
-{
-}
-
-ImageAryData::ImageAryData( const OUString &aName,
-                            sal_uInt16 nId, const BitmapEx &aBitmap )
-        : maName( aName ), mnId( nId ), maBitmapEx( aBitmap )
-{
-}
-
-ImageAryData::~ImageAryData()
-{
-}
-
-ImageAryData& ImageAryData::operator=( const ImageAryData& rData )
-{
-    maName = rData.maName;
-    mnId = rData.mnId;
-    maBitmapEx = rData.maBitmapEx;
-
-    return *this;
-}
-
-void ImageAryData::Load(const OUString &rPrefix)
-{
-    OUString aIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
-
-    OUString aFileName = rPrefix;
-    aFileName += maName;
-
-    bool bSuccess = ImageTree::get().loadImage(aFileName, aIconTheme, maBitmapEx, true);
-
-    /* If the uno command has parameters, passed in from a toolbar,
-     * recover from failure by removing the parameters from the file name
-     */
-    if (!bSuccess && aFileName.indexOf("%3f") > 0)
-    {
-        sal_Int32 nStart = aFileName.indexOf("%3f");
-        sal_Int32 nEnd = aFileName.lastIndexOf(".");
-
-        aFileName = aFileName.replaceAt(nStart, nEnd - nStart, "");
-        bSuccess = ImageTree::get().loadImage(aFileName, aIconTheme, maBitmapEx, true);
-    }
-
-    SAL_WARN_IF(!bSuccess, "fwk.uiconfiguration", "Failed to load image '" << aFileName
-              << "' from icon theme '" << aIconTheme << "'");
-}
-
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/uiconfiguration/ImageList.cxx b/framework/source/uiconfiguration/ImageList.cxx
index 0bb10d3d2bdb..100e152b17fc 100644
--- a/framework/source/uiconfiguration/ImageList.cxx
+++ b/framework/source/uiconfiguration/ImageList.cxx
@@ -29,7 +29,6 @@
 #include <vcl/image.hxx>
 #include <vcl/imagerepository.hxx>
 #include <vcl/ImageTree.hxx>
-#include "image.h"
 #include "ImageList.hxx"
 
 ImageList::ImageList()
@@ -41,48 +40,40 @@ ImageList::ImageList(const std::vector< OUString >& rNameVector,
 {
     SAL_INFO( "vcl", "vcl: ImageList::ImageList(const vector< OUString >& ..." );
 
-    ImplInit( sal::static_int_cast< sal_uInt16 >( rNameVector.size() ), Size() );
+    maImages.reserve( rNameVector.size() );
 
-    mpImplData->maPrefix = rPrefix;
+    maPrefix = rPrefix;
     for( size_t i = 0; i < rNameVector.size(); ++i )
     {
-        mpImplData->AddImage( rNameVector[ i ], static_cast< sal_uInt16 >( i ) + 1, BitmapEx() );
+        ImplAddImage( rNameVector[ i ], static_cast< sal_uInt16 >( i ) + 1, BitmapEx() );
     }
 }
 
-void ImageList::ImplInit( sal_uInt16 nItems, const Size &rSize )
-{
-    mpImplData.reset(new ImplImageList);
-    mpImplData->maImages.reserve( nItems );
-    mpImplData->maImageSize = rSize;
-}
-
 // FIXME: Rather a performance hazard
 BitmapEx ImageList::GetAsHorizontalStrip() const
 {
-    Size aSize( mpImplData->maImageSize );
-    sal_uInt16 nCount = GetImageCount();
+    sal_uInt16 nCount = maImages.size();
     if( !nCount )
         return BitmapEx();
-    aSize.setWidth( aSize.Width() * nCount );
+    Size aSize( maImageSize.Width() * nCount, maImageSize.Height() );
 
     // Load any stragglers
     for (sal_uInt16 nIdx = 0; nIdx < nCount; nIdx++)
     {
-        ImageAryData *pData = mpImplData->maImages[ nIdx ].get();
+        ImageAryData *pData = maImages[ nIdx ].get();
         if( pData->IsLoadable() )
-            pData->Load( mpImplData->maPrefix );
+            ImplLoad(*pData);
     }
 
-    BitmapEx aTempl = mpImplData->maImages[ 0 ]->maBitmapEx;
+    BitmapEx aTempl = maImages[ 0 ]->maBitmapEx;
     BitmapEx aResult( aTempl, Point(), aSize );
 
-    tools::Rectangle aSrcRect( Point( 0, 0 ), mpImplData->maImageSize );
+    tools::Rectangle aSrcRect( Point( 0, 0 ), maImageSize );
     for (sal_uInt16 nIdx = 0; nIdx < nCount; nIdx++)
     {
-        tools::Rectangle aDestRect( Point( nIdx * mpImplData->maImageSize.Width(), 0 ),
-                             mpImplData->maImageSize );
-        ImageAryData *pData = mpImplData->maImages[ nIdx ].get();
+        tools::Rectangle aDestRect( Point( nIdx * maImageSize.Width(), 0 ),
+                             maImageSize );
+        ImageAryData *pData = maImages[ nIdx ].get();
         aResult.CopyPixel( aDestRect, aSrcRect, &pData->maBitmapEx);
     }
 
@@ -101,32 +92,32 @@ void ImageList::InsertFromHorizontalStrip( const BitmapEx &rBitmapEx,
     DBG_ASSERT (rBitmapEx.GetSizePixel().Width() % nItems == 0,
                 "ImageList::InsertFromHorizontalStrip - very odd size");
     aSize.setWidth( aSize.Width() / nItems );
-    ImplInit( nItems, aSize );
+    maImages.clear();
+    maNameHash.clear();
+    maImages.reserve( nItems );
+    maImageSize = aSize;
+    maPrefix.clear();
 
     for (sal_uInt16 nIdx = 0; nIdx < nItems; nIdx++)
     {
         BitmapEx aBitmap( rBitmapEx, Point( nIdx * aSize.Width(), 0 ), aSize );
-        mpImplData->AddImage( rNameVector[ nIdx ], nIdx + 1, aBitmap );
+        ImplAddImage( rNameVector[ nIdx ], nIdx + 1, aBitmap );
     }
 }
 
 sal_uInt16 ImageList::ImplGetImageId( const OUString& rImageName ) const
 {
-    ImageAryData *pImg = mpImplData->maNameHash[ rImageName ];
-    if( pImg )
-        return pImg->mnId;
-    else
+    auto it = maNameHash.find( rImageName );
+    if (it == maNameHash.end())
         return 0;
+    return it->second->mnId;
 }
 
 void ImageList::AddImage( const OUString& rImageName, const Image& rImage )
 {
     SAL_WARN_IF( GetImagePos( rImageName ) != IMAGELIST_IMAGE_NOTFOUND, "vcl", "ImageList::AddImage() - ImageName already exists" );
 
-    if( !mpImplData )
-        ImplInit( 0, rImage.GetSizePixel() );
-
-    mpImplData->AddImage( rImageName, GetImageCount() + 1,
+    ImplAddImage( rImageName, GetImageCount() + 1,
                           rImage.GetBitmapEx() );
 }
 
@@ -138,18 +129,18 @@ void ImageList::ReplaceImage( const OUString& rImageName, const Image& rImage )
     {
         //Just replace the bitmap rather than doing RemoveImage / AddImage
         //which breaks index-based iteration.
-        ImageAryData *pImg = mpImplData->maNameHash[ rImageName ];
+        ImageAryData *pImg = maNameHash[ rImageName ];
         pImg->maBitmapEx = rImage.GetBitmapEx();
     }
 }
 
 void ImageList::RemoveImage( sal_uInt16 nId )
 {
-    for( size_t i = 0; i < mpImplData->maImages.size(); ++i )
+    for( size_t i = 0; i < maImages.size(); ++i )
     {
-        if( mpImplData->maImages[ i ]->mnId == nId )
+        if( maImages[ i ]->mnId == nId )
         {
-            mpImplData->RemoveImage( static_cast< sal_uInt16 >( i ) );
+            ImplRemoveImage( static_cast< sal_uInt16 >( i ) );
             break;
         }
     }
@@ -157,33 +148,27 @@ void ImageList::RemoveImage( sal_uInt16 nId )
 
 Image ImageList::GetImage( const OUString& rImageName ) const
 {
-    if( mpImplData )
-    {
-        ImageAryData *pImg = mpImplData->maNameHash[ rImageName ];
-
-        if( pImg )
-        {
-            if( pImg->IsLoadable() )
-                pImg->Load( mpImplData->maPrefix );
-            return Image( pImg->maBitmapEx );
-        }
-    }
-
-    return Image();
+    auto it = maNameHash.find( rImageName );
+    if (it == maNameHash.end())
+        return Image();
+    ImageAryData *pImg = it->second;
+    if( pImg->IsLoadable() )
+        ImplLoad( *pImg );
+    return Image( pImg->maBitmapEx );
 }
 
 sal_uInt16 ImageList::GetImageCount() const
 {
-    return mpImplData ? static_cast< sal_uInt16 >( mpImplData->maImages.size() ) : 0;
+    return static_cast< sal_uInt16 >( maImages.size() );
 }
 
 sal_uInt16 ImageList::GetImagePos( const OUString& rImageName ) const
 {
-    if( mpImplData && !rImageName.isEmpty() )
+    if( !rImageName.isEmpty() )
     {
-        for( size_t i = 0; i < mpImplData->maImages.size(); i++ )
+        for( size_t i = 0; i < maImages.size(); i++ )
         {
-            if (mpImplData->maImages[i]->maName == rImageName)
+            if (maImages[i]->maName == rImageName)
                 return static_cast< sal_uInt16 >( i );
         }
     }
@@ -193,18 +178,12 @@ sal_uInt16 ImageList::GetImagePos( const OUString& rImageName ) const
 
 sal_uInt16 ImageList::GetImageId( sal_uInt16 nPos ) const
 {
-    if( mpImplData && (nPos < GetImageCount()) )
-        return mpImplData->maImages[ nPos ]->mnId;
-
-    return 0;
+    return maImages[ nPos ]->mnId;
 }
 
 OUString ImageList::GetImageName( sal_uInt16 nPos ) const
 {
-    if( mpImplData && (nPos < GetImageCount()) )
-        return mpImplData->maImages[ nPos ]->maName;
-
-    return OUString();
+    return maImages[ nPos ]->maName;
 }
 
 void ImageList::GetImageNames( std::vector< OUString >& rNames ) const
@@ -213,30 +192,54 @@ void ImageList::GetImageNames( std::vector< OUString >& rNames ) const
 
     rNames = std::vector< OUString >();
 
-    if( mpImplData )
+    for(auto const & pImage : maImages)
     {
-        for(auto const & pImage : mpImplData->maImages)
-        {
-            const OUString& rName( pImage->maName );
-            if( !rName.isEmpty())
-                rNames.push_back( rName );
-        }
+        const OUString& rName( pImage->maName );
+        if( !rName.isEmpty())
+            rNames.push_back( rName );
     }
 }
 
-bool ImageList::operator==( const ImageList& rImageList ) const
+void ImageList::ImplAddImage( const OUString &aName,
+                              sal_uInt16 nId, const BitmapEx &aBitmapEx )
+{
+    ImageAryData *pImg = new ImageAryData{ aName, nId, aBitmapEx };
+    maImages.emplace_back( pImg );
+    if( !aName.isEmpty() )
+        maNameHash [ aName ] = pImg;
+}
+
+void ImageList::ImplRemoveImage( sal_uInt16 nPos )
+{
+    ImageAryData *pImg = maImages[ nPos ].get();
+    if( !pImg->maName.isEmpty() )
+        maNameHash.erase( pImg->maName );
+    maImages.erase( maImages.begin() + nPos );
+}
+
+void ImageList::ImplLoad(ImageAryData& rImageData) const
 {
-    bool bRet = false;
+    OUString aIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
 
-    if( rImageList.mpImplData == mpImplData )
-        bRet = true;
-    else if( !rImageList.mpImplData || !mpImplData )
-        bRet = false;
-    else if( rImageList.GetImageCount() == GetImageCount() &&
-              rImageList.mpImplData->maImageSize == mpImplData->maImageSize )
-        bRet = true; // strange semantic
+    OUString aFileName = maPrefix + rImageData.maName;
 
-    return bRet;
+    bool bSuccess = ImageTree::get().loadImage(aFileName, aIconTheme, rImageData.maBitmapEx, true);
+
+    /* If the uno command has parameters, passed in from a toolbar,
+     * recover from failure by removing the parameters from the file name
+     */
+    if (!bSuccess && aFileName.indexOf("%3f") > 0)
+    {
+        sal_Int32 nStart = aFileName.indexOf("%3f");
+        sal_Int32 nEnd = aFileName.lastIndexOf(".");
+
+        aFileName = aFileName.replaceAt(nStart, nEnd - nStart, "");
+        bSuccess = ImageTree::get().loadImage(aFileName, aIconTheme, rImageData.maBitmapEx, true);
+    }
+
+    SAL_WARN_IF(!bSuccess, "fwk.uiconfiguration", "Failed to load image '" << aFileName
+              << "' from icon theme '" << aIconTheme << "'");
 }
 
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/uiconfiguration/ImageList.hxx b/framework/source/uiconfiguration/ImageList.hxx
index 85c9459a7b5d..f610692fb672 100644
--- a/framework/source/uiconfiguration/ImageList.hxx
+++ b/framework/source/uiconfiguration/ImageList.hxx
@@ -20,6 +20,20 @@
 #ifndef FRAMEWORK_SOURCE_UICONFIGURATION_IMAGELIST_HXX
 #define FRAMEWORK_SOURCE_UICONFIGURATION_IMAGELIST_HXX
 
+#include <vcl/bitmapex.hxx>
+#include <unordered_map>
+#include <vector>
+
+// Images identified by either name, or by id
+struct ImageAryData
+{
+    OUString                maName;
+    sal_uInt16              mnId;
+    BitmapEx                maBitmapEx;
+
+    bool IsLoadable() { return maBitmapEx.IsEmpty() && !maName.isEmpty(); }
+};
+
 class ImageList
 {
 public:
@@ -47,15 +61,17 @@ public:
     OUString        GetImageName( sal_uInt16 nPos ) const;
     void            GetImageNames( ::std::vector< OUString >& rNames ) const;
 
-    bool            operator==( const ImageList& rImageList ) const;
-    bool            operator!=( const ImageList& rImageList ) const { return !(ImageList::operator==( rImageList )); }
-
 private:
 
-    std::shared_ptr<ImplImageList> mpImplData;
+    std::vector< std::unique_ptr<ImageAryData> >   maImages;
+    std::unordered_map< OUString, ImageAryData * > maNameHash;
+    OUString               maPrefix;
+    Size                   maImageSize;
 
-    void    ImplInit( sal_uInt16 nItems, const Size &rSize );
     sal_uInt16  ImplGetImageId( const OUString& rImageName ) const;
+    void ImplAddImage( const OUString &aName, sal_uInt16 nId, const BitmapEx &aBitmapEx );
+    void ImplRemoveImage( sal_uInt16 nPos );
+    void ImplLoad(ImageAryData&) const;
 };
 
 #endif // INCLUDED_VCL_IMAGE_HXX
diff --git a/framework/source/uiconfiguration/ImplImageList.cxx b/framework/source/uiconfiguration/ImplImageList.cxx
deleted file mode 100644
index 1c594f16bf89..000000000000
--- a/framework/source/uiconfiguration/ImplImageList.cxx
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*- 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 <vcl/outdev.hxx>
-#include <vcl/bitmapex.hxx>
-#include <vcl/alpha.hxx>
-#include <vcl/window.hxx>
-#include <vcl/bitmapaccess.hxx>
-#include <vcl/virdev.hxx>
-#include <vcl/image.hxx>
-#include <vcl/settings.hxx>
-
-#include "image.h"
-#include <memory>
-
-ImplImageList::ImplImageList()
-{
-}
-
-ImplImageList::ImplImageList( const ImplImageList &aSrc )
-    : maPrefix(aSrc.maPrefix)
-    , maImageSize(aSrc.maImageSize)
-{
-    maImages.reserve( aSrc.maImages.size() );
-    for (auto const& elem : aSrc.maImages)
-    {
-        ImageAryData* pAryData = new ImageAryData(*elem);
-        maImages.emplace_back( pAryData );
-        if( !pAryData->maName.isEmpty() )
-            maNameHash [ pAryData->maName ] = pAryData;
-    }
-}
-
-ImplImageList::~ImplImageList()
-{
-}
-
-void ImplImageList::AddImage( const OUString &aName,
-                              sal_uInt16 nId, const BitmapEx &aBitmapEx )
-{
-    ImageAryData *pImg = new ImageAryData( aName, nId, aBitmapEx );
-    maImages.emplace_back( pImg );
-    if( !aName.isEmpty() )
-        maNameHash [ aName ] = pImg;
-}
-
-void ImplImageList::RemoveImage( sal_uInt16 nPos )
-{
-    ImageAryData *pImg = maImages[ nPos ].get();
-    if( !pImg->maName.isEmpty() )
-        maNameHash.erase( pImg->maName );
-    maImages.erase( maImages.begin() + nPos );
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/uiconfiguration/image.h b/framework/source/uiconfiguration/image.h
deleted file mode 100644
index 96c952d3dfe3..000000000000
--- a/framework/source/uiconfiguration/image.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#ifndef FRAMEWORK_SOURCE_UICONFIGURATION_IMAGE_H
-#define FRAMEWORK_SOURCE_UICONFIGURATION_IMAGE_H
-
-#include <vcl/bitmapex.hxx>
-
-#include <unordered_map>
-#include <vector>
-
-struct ImageAryData
-{
-    OUString maName;
-    // Images identified by either name, or by id
-    sal_uInt16              mnId;
-    BitmapEx                maBitmapEx;
-
-    ImageAryData( const OUString &aName,
-                  sal_uInt16 nId, const BitmapEx &aBitmap );
-    ImageAryData( const ImageAryData& rData );
-    ~ImageAryData();
-
-    bool IsLoadable() { return maBitmapEx.IsEmpty() && !maName.isEmpty(); }
-    void Load(const OUString &rPrefix);
-
-    ImageAryData&   operator=( const ImageAryData& rData );
-};
-
-struct ImplImageList
-{
-    typedef std::unordered_map< OUString, ImageAryData * >
-        ImageAryDataNameHash;
-
-    std::vector< std::unique_ptr<ImageAryData> >  maImages;
-    ImageAryDataNameHash   maNameHash;
-    OUString               maPrefix;
-    Size                   maImageSize;
-
-    ImplImageList();
-    ImplImageList( const ImplImageList &aSrc );
-    ~ImplImageList();
-
-    void AddImage( const OUString &aName,
-                   sal_uInt16 nId, const BitmapEx &aBitmapEx );
-    void RemoveImage( sal_uInt16 nPos );
-};
-
-#endif // INCLUDED_VCL_INC_IMAGE_H
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 06c7b477cabae385f2f9c2eb50b69dc750504366
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Mon Nov 26 19:50:38 2018 +0000
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Tue Sep 24 13:58:52 2019 +0100

    Propagate stock info through slide layouts.
    
    (cherry picked from commit f107161bbd0eb4ee5766f5f983d18b32b929b15c)
    
    Change-Id: If717db82fe6ab14bbf32225c1f1c95f44954f011

diff --git a/sd/source/ui/controller/slidelayoutcontroller.cxx b/sd/source/ui/controller/slidelayoutcontroller.cxx
index 6f4ba93c1e92..6d4396be865b 100644
--- a/sd/source/ui/controller/slidelayoutcontroller.cxx
+++ b/sd/source/ui/controller/slidelayoutcontroller.cxx
@@ -134,7 +134,7 @@ static void fillLayoutValueSet( ValueSet* pValue, const snewfoil_value_info_layo
         OUString aText(SdResId(pInfo->mpStrResId));
         Image aImg("private:graphicrepository/" + OUString::createFromAscii(pInfo->msBmpResId));
         pValue->InsertItem(static_cast<sal_uInt16>(pInfo->maAutoLayout)+1, aImg, aText);
-        aLayoutItemSize.setWidth( std::max( aLayoutItemSize.Width(),  aImg.GetSizePixel().Width()  ) );
+        aLayoutItemSize.setWidth( std::max( aLayoutItemSize.Width(),   aImg.GetSizePixel().Width()  ) );
         aLayoutItemSize.setHeight( std::max( aLayoutItemSize.Height(), aImg.GetSizePixel().Height() ) );
     }
 
diff --git a/sd/source/ui/sidebar/LayoutMenu.cxx b/sd/source/ui/sidebar/LayoutMenu.cxx
index e0da346e9d6a..c336dcd1cfaa 100644
--- a/sd/source/ui/sidebar/LayoutMenu.cxx
+++ b/sd/source/ui/sidebar/LayoutMenu.cxx
@@ -529,12 +529,16 @@ void LayoutMenu::Fill()
     {
         if ((WritingMode_TB_RL != pInfo->meWritingMode) || bVertical)
         {
-            BitmapEx aBmp(OUString::createFromAscii(pInfo->msBmpResId));
+            Image aImg("private:graphicrepository/" + OUString::createFromAscii(pInfo->msBmpResId));
 
             if (bRightToLeft && (WritingMode_TB_RL != pInfo->meWritingMode))
-                aBmp.Mirror (BmpMirrorFlags::Horizontal);
+            { // FIXME: avoid interpolating RTL layouts.
+                BitmapEx aRTL = aImg.GetBitmapEx();
+                aRTL.Mirror(BmpMirrorFlags::Horizontal);
+                aImg = Image(aRTL);
+            }
 
-            InsertItem(i, Image(aBmp), SdResId(pInfo->mpStrResId));
+            InsertItem(i, aImg, SdResId(pInfo->mpStrResId));
             SetItemData (i, new AutoLayout(pInfo->maAutoLayout));
         }
     }
commit 117676cd8bac08c40cb6511fffdc944bec6f90f8
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Mon Nov 26 14:00:08 2018 +0000
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Tue Sep 24 13:58:52 2019 +0100

    Use HiDPI scaling to load scaled images.
    
    We render these at apparently the same pixel size as normal images,
    but the underlying canvas is larger so these then end up pixel-matching
    the true underlying grid.
    
    Change-Id: Ic4b749127e9c81da78d06b34d9f88c5635dc64b9
    Reviewed-on: https://gerrit.libreoffice.org/64044
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/inc/image.h b/vcl/inc/image.h
index f966a8c62c1f..c9fb5393191a 100644
--- a/vcl/inc/image.h
+++ b/vcl/inc/image.h
@@ -44,9 +44,13 @@ struct ImplImage
 
     /// get size in co-ordinates not scaled for HiDPI
     Size getSizePixel();
+    /// Legacy - the original bitmap
     BitmapEx getBitmapEx(bool bDisabled = false);
+    /// Taking account of HiDPI scaling
+    BitmapEx getBitmapExForHiDPI(bool bDisabled = false);
     bool isEqual(const ImplImage &ref) const;
     bool isSizeEmpty() const { return maSizePixel == Size(0, 0); }
+    bool loadStockAtScale(double fScale, BitmapEx &rBitmapEx);
 };
 
 #endif // INCLUDED_VCL_INC_IMAGE_H
diff --git a/vcl/source/image/Image.cxx b/vcl/source/image/Image.cxx
index 8bce4839a1ea..ecb514c5bbac 100644
--- a/vcl/source/image/Image.cxx
+++ b/vcl/source/image/Image.cxx
@@ -111,13 +111,9 @@ void Image::Draw(OutputDevice* pOutDev, const Point& rPos, DrawImageFlags nStyle
     if (!mpImplData || (!pOutDev->IsDeviceOutputNecessary() && pOutDev->GetConnectMetaFile() == nullptr))
         return;
 
-    const Point aSrcPos(0, 0);
-    Size aBitmapSizePixel = mpImplData->getSizePixel();
+    Size aOutSize = pSize ? *pSize : pOutDev->PixelToLogic(mpImplData->getSizePixel());
 
-    Size aOutSize = pSize ? *pSize : pOutDev->PixelToLogic(aBitmapSizePixel);
-
-    // FIXME: do the HiDPI scaling fun here [!] =)
-    BitmapEx aRenderBmp = mpImplData->getBitmapEx(!!(nStyle & DrawImageFlags::Disable));
+    BitmapEx aRenderBmp = mpImplData->getBitmapExForHiDPI(!!(nStyle & DrawImageFlags::Disable));
 
     if (!(nStyle & DrawImageFlags::Disable) &&
         (nStyle & (DrawImageFlags::ColorTransform | DrawImageFlags::Highlight |
@@ -154,7 +150,7 @@ void Image::Draw(OutputDevice* pOutDev, const Point& rPos, DrawImageFlags nStyle
         aRenderBmp = aTempBitmapEx;
     }
 
-    pOutDev->DrawBitmapEx(rPos, aOutSize, aSrcPos, aBitmapSizePixel, aRenderBmp);
+    pOutDev->DrawBitmapEx(rPos, aOutSize, aRenderBmp);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/image/ImplImage.cxx b/vcl/source/image/ImplImage.cxx
index 471dcb091e3d..95d605e47173 100644
--- a/vcl/source/image/ImplImage.cxx
+++ b/vcl/source/image/ImplImage.cxx
@@ -18,6 +18,7 @@
  */
 
 #include <sal/log.hxx>
+#include <vcl/svapp.hxx>
 #include <vcl/outdev.hxx>
 #include <vcl/bitmapex.hxx>
 #include <vcl/alpha.hxx>
@@ -49,6 +50,21 @@ ImplImage::ImplImage(const OUString &aStockName)
 {
 }
 
+bool ImplImage::loadStockAtScale(double fScale, BitmapEx &rBitmapEx)
+{
+    BitmapEx aBitmapEx;
+    OUString aIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
+    if (!ImageTree::get().loadImage(maStockName, aIconTheme, aBitmapEx, true,
+                                    fScale * 100.0,
+                                    ImageLoadFlags::IgnoreScalingFactor))
+    {
+        SAL_WARN("vcl", "Failed to load scaled image from " << maStockName << " at " << fScale);
+        return false;
+    }
+    rBitmapEx = aBitmapEx;
+    return true;
+}
+
 Size ImplImage::getSizePixel()
 {
     Size aRet;
@@ -56,13 +72,11 @@ Size ImplImage::getSizePixel()
         aRet = maSizePixel;
     else if (isStock())
     {
-        BitmapEx aBitmapEx;
-        if (vcl::ImageRepository::loadImage(maStockName, aBitmapEx))
+        if (loadStockAtScale(1.0, maBitmapEx))
         {
             assert(!maDisabledBitmapEx);
             assert(maBitmapChecksum == 0);
-            maBitmapEx = aBitmapEx;
-            maSizePixel = aBitmapEx.GetSizePixel();
+            maSizePixel = maBitmapEx.GetSizePixel();
             aRet = maSizePixel;
         }
         else
@@ -102,4 +116,18 @@ bool ImplImage::isEqual(const ImplImage &ref) const
         return maBitmapEx == ref.maBitmapEx;
 }
 
+BitmapEx ImplImage::getBitmapExForHiDPI(bool bDisabled)
+{
+    if (isStock())
+    {   // check we have the right bitmap cached.
+        // FIXME: DPI scaling should be tied to the outdev really ...
+        double fScale = comphelper::LibreOfficeKit::getDPIScale();
+        Size aTarget(maSizePixel.Width()*fScale,
+                         maSizePixel.Height()*fScale);
+        if (maBitmapEx.GetSizePixel() != aTarget)
+            loadStockAtScale(fScale, maBitmapEx);
+    }
+    return getBitmapEx(bDisabled);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 635f94b4368ffe68d61a85f46b95a9f3e2982bd8
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Mon Nov 26 13:24:03 2018 +0000
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Tue Sep 24 13:58:52 2019 +0100

    Add explicit API scaling via ImageTree API.
    
    Also add image scale to in-memory cache lookup.
    
    Change-Id: I1e84b922d4a9ab2f1723c5cb8a72f295c6940504
    Reviewed-on: https://gerrit.libreoffice.org/64043
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/include/vcl/ImageTree.hxx b/include/vcl/ImageTree.hxx
index 6598c34c09e9..4b49a31f30b9 100644
--- a/include/vcl/ImageTree.hxx
+++ b/include/vcl/ImageTree.hxx
@@ -64,6 +64,12 @@ public:
         BitmapEx & bitmap, bool localized,
         const ImageLoadFlags eFlags = ImageLoadFlags::NONE);
 
+    VCL_DLLPUBLIC bool loadImage(
+        OUString const & name, OUString const & style,
+        BitmapEx & bitmap, bool localized,
+        sal_Int32 nScalePercentage,
+        const ImageLoadFlags eFlags = ImageLoadFlags::NONE);
+
     VCL_DLLPUBLIC css::uno::Reference<css::container::XNameAccess> const & getNameAccess();
 
 
diff --git a/vcl/inc/implimagetree.hxx b/vcl/inc/implimagetree.hxx
index 3768b04388b3..1e81aba8fac8 100644
--- a/vcl/inc/implimagetree.hxx
+++ b/vcl/inc/implimagetree.hxx
@@ -46,14 +46,17 @@ struct ImageRequestParameters
     bool mbLocalized;
     ImageLoadFlags const meFlags;
     bool mbWriteImageToCache;
+    sal_Int32 mnScalePercentage;
 
-    ImageRequestParameters(const OUString & rName, const OUString & rStyle, BitmapEx& rBitmap, bool bLocalized, ImageLoadFlags eFlags)
+    ImageRequestParameters(const OUString & rName, const OUString & rStyle, BitmapEx& rBitmap, bool bLocalized,
+                           ImageLoadFlags eFlags, sal_Int32 nScalePercentage)
         : msName(rName)
         , msStyle(rStyle)
         , mrBitmap(rBitmap)
         , mbLocalized(bLocalized)
         , meFlags(eFlags)
         , mbWriteImageToCache(false)
+        , mnScalePercentage(nScalePercentage)
     {}
 
     bool convertToDarkTheme();
@@ -75,7 +78,8 @@ public:
     bool loadImage(
         OUString const & name, OUString const & style,
         BitmapEx & bitmap, bool localized,
-        const ImageLoadFlags eFlags);
+        const ImageLoadFlags eFlags,
+        sal_Int32 nScalePercentage = -1);
 
     /** a crude form of life cycle control (called from DeInitVCL; otherwise,
      *  if the ImplImageTree singleton were destroyed during exit that would
@@ -88,14 +92,15 @@ private:
     ImplImageTree(const ImplImageTree&) = delete;
     ImplImageTree& operator=(const ImplImageTree&) = delete;
 
-    typedef std::unordered_map<OUString, std::pair<bool, BitmapEx>> IconCache;
+    typedef std::unordered_map<OUString, std::pair<bool,BitmapEx>> IconCache;
+    typedef std::unordered_map<sal_Int32, std::unique_ptr<IconCache>> ScaledIconCache;
     typedef std::unordered_map<OUString, OUString> IconLinkHash;
 
     struct IconSet
     {
         OUString maURL;
         css::uno::Reference<css::container::XNameAccess> maNameAccess;
-        IconCache maIconCache;
+        ScaledIconCache maScaledIconCaches;
         IconLinkHash maLinkHash;
 
         IconSet()
@@ -128,6 +133,8 @@ private:
 
     void createStyle();
 
+    IconCache &getIconCache(ImageRequestParameters& rParameters);
+
     bool iconCacheLookup(ImageRequestParameters& rParameters);
 
     bool findImage(std::vector<OUString> const & rPaths, ImageRequestParameters& rParameters);
diff --git a/vcl/source/image/ImageTree.cxx b/vcl/source/image/ImageTree.cxx
index 2e20183b0da5..826671e110ec 100644
--- a/vcl/source/image/ImageTree.cxx
+++ b/vcl/source/image/ImageTree.cxx
@@ -37,9 +37,17 @@ std::shared_ptr<SvMemoryStream> ImageTree::getImageStream(OUString const & rName
 
 bool ImageTree::loadImage(OUString const & rName, OUString const & rStyle,
                           BitmapEx & rBitmap, bool bLocalized,
+                          sal_Int32 nScalePercentage,
                           const ImageLoadFlags eFlags)
 {
-    return mpImplImageTree->loadImage(rName, rStyle, rBitmap, bLocalized, eFlags);
+    return mpImplImageTree->loadImage(rName, rStyle, rBitmap, bLocalized, eFlags, nScalePercentage);
+}
+
+bool ImageTree::loadImage(OUString const & rName, OUString const & rStyle,
+                          BitmapEx & rBitmap, bool bLocalized,
+                          const ImageLoadFlags eFlags)
+{
+    return loadImage(rName, rStyle, rBitmap, bLocalized, -1, eFlags);
 }
 
 css::uno::Reference<css::container::XNameAccess> const & ImageTree::getNameAccess()
diff --git a/vcl/source/image/ImplImageTree.cxx b/vcl/source/image/ImplImageTree.cxx
index 1fed00908365..22fd194b3a8d 100644
--- a/vcl/source/image/ImplImageTree.cxx
+++ b/vcl/source/image/ImplImageTree.cxx
@@ -69,6 +69,8 @@ sal_Int32 ImageRequestParameters::scalePercentage()
     sal_Int32 aScalePercentage = 100;
     if (!(meFlags & ImageLoadFlags::IgnoreScalingFactor))
         aScalePercentage = Application::GetDefaultDevice()->GetDPIScalePercentage();
+    else if (mnScalePercentage > 0)
+        aScalePercentage = mnScalePercentage;
     return aScalePercentage;
 }
 
@@ -96,17 +98,17 @@ OUString createPath(OUString const & name, sal_Int32 pos, OUString const & local
     return name.copy(0, pos + 1) + locale + name.copy(pos);
 }
 
-OUString getIconCacheUrl(OUString const & sStyle, OUString const & sVariant, OUString const & sName)
+OUString getIconCacheUrl(OUString const & sVariant, ImageRequestParameters const & rParameters)
 {
     OUString sUrl("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/cache/");
-    sUrl += sStyle + "/" + sVariant + "/" + sName;
+    sUrl += rParameters.msStyle + "/" + sVariant + "/" + rParameters.msName;
     rtl::Bootstrap::expandMacros(sUrl);
     return sUrl;
 }
 
-OUString createIconCacheUrl(OUString const & sStyle, OUString const & sVariant, OUString const & sName)
+OUString createIconCacheUrl(OUString const & sVariant, ImageRequestParameters const & rParameters)
 {
-    OUString sUrl(getIconCacheUrl(sStyle, sVariant, sName));
+    OUString sUrl(getIconCacheUrl(sVariant, rParameters));
     OUString sDir = sUrl.copy(0, sUrl.lastIndexOf('/'));
     osl::Directory::createPath(sDir);
     return sUrl;
@@ -315,14 +317,15 @@ OUString ImplImageTree::fallbackStyle(const OUString& rsStyle)
     return sResult;
 }
 
-bool ImplImageTree::loadImage(OUString const & rName, OUString const & rStyle, BitmapEx & rBitmap, bool localized, const ImageLoadFlags eFlags)
+bool ImplImageTree::loadImage(OUString const & rName, OUString const & rStyle, BitmapEx & rBitmap, bool localized,
+                              const ImageLoadFlags eFlags, sal_Int32 nScalePercentage)
 {
     OUString aCurrentStyle(rStyle);
     while (!aCurrentStyle.isEmpty())
     {
         try
         {
-            ImageRequestParameters aParameters(rName, aCurrentStyle, rBitmap, localized, eFlags);
+            ImageRequestParameters aParameters(rName, aCurrentStyle, rBitmap, localized, eFlags, nScalePercentage);
             if (doLoadImage(aParameters))
                 return true;
         }
@@ -349,7 +352,7 @@ static OUString createVariant(ImageRequestParameters& rParameters)
 
 static bool loadDiskCachedVersion(OUString const & sVariant, ImageRequestParameters& rParameters)
 {
-    OUString sUrl(getIconCacheUrl(rParameters.msStyle, sVariant, rParameters.msName));
+    OUString sUrl(getIconCacheUrl(sVariant, rParameters));
     if (!urlExists(sUrl))
         return false;
     SvFileStream aFileStream(sUrl, StreamMode::READ);
@@ -361,7 +364,7 @@ static bool loadDiskCachedVersion(OUString const & sVariant, ImageRequestParamet
 
 static void cacheBitmapToDisk(OUString const & sVariant, ImageRequestParameters const & rParameters)
 {
-    OUString sUrl(createIconCacheUrl(rParameters.msStyle, sVariant, rParameters.msName));
+    OUString sUrl(createIconCacheUrl(sVariant, rParameters));
     vcl::PNGWriter aWriter(rParameters.mrBitmap);
     try
     {
@@ -382,9 +385,7 @@ bool ImplImageTree::doLoadImage(ImageRequestParameters& rParameters)
 
     OUString aVariant = createVariant(rParameters);
     if (loadDiskCachedVersion(aVariant, rParameters))
-    {
         return true;
-    }
 
     if (!rParameters.mrBitmap.IsEmpty())
         rParameters.mrBitmap.SetEmpty();
@@ -414,7 +415,7 @@ bool ImplImageTree::doLoadImage(ImageRequestParameters& rParameters)
         {
             cacheBitmapToDisk(aVariant, rParameters);
         }
-        getCurrentIconSet().maIconCache[rParameters.msName] = std::make_pair(rParameters.mbLocalized, rParameters.mrBitmap);
+        getIconCache(rParameters)[rParameters.msName] = std::make_pair(rParameters.mbLocalized, rParameters.mrBitmap);
     }
 
     return bFound;
@@ -482,9 +483,20 @@ void ImplImageTree::createStyle()
     loadImageLinks();
 }
 
+/// Find an icon cache for the right scale factor
+ImplImageTree::IconCache &ImplImageTree::getIconCache(ImageRequestParameters& rParameters)
+{
+    IconSet &rSet = getCurrentIconSet();
+    auto it = rSet.maScaledIconCaches.find(rParameters.mnScalePercentage);
+    if ( it != rSet.maScaledIconCaches.end() )
+        return *it->second.get();
+    rSet.maScaledIconCaches[rParameters.mnScalePercentage] = std::unique_ptr<IconCache>(new IconCache);
+    return *rSet.maScaledIconCaches[rParameters.mnScalePercentage].get();
+}
+
 bool ImplImageTree::iconCacheLookup(ImageRequestParameters& rParameters)
 {
-    IconCache& rIconCache = getCurrentIconSet().maIconCache;
+    IconCache& rIconCache = getIconCache(rParameters);
 
     IconCache::iterator i(rIconCache.find(getRealImageName(rParameters.msName)));
     if (i != rIconCache.end() && i->second.first == rParameters.mbLocalized)
@@ -513,6 +525,7 @@ bool ImplImageTree::findImage(std::vector<OUString> const & rPaths, ImageRequest
             (void)ok; // prevent unused warning in release build
 
             loadImageFromStream(wrapStream(aStream), rPath, rParameters);
+
             return true;
         }
     }
commit 5261c30266cf920f1ba0bd75874e498f3aca004d
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Mon Nov 26 11:06:20 2018 +0000
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Tue Sep 24 13:58:52 2019 +0100

    Preserve stock images until render time.
    
    This allows us to choose to render HiDPI images at the right time,
    when we have the DPI of the device to render to.
    
    The first step in a better, and more industry standard way of
    improving our UI for HiDPI via rendering level scaling that should
    retain a consistent look across the app with many fewer changes.
    
    Change-Id: I36681f3242cb650de4f0b2d0fcdffbe5618e30fc
    Reviewed-on: https://gerrit.libreoffice.org/64040
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/sd/source/ui/controller/slidelayoutcontroller.cxx b/sd/source/ui/controller/slidelayoutcontroller.cxx
index 611920043515..6f4ba93c1e92 100644
--- a/sd/source/ui/controller/slidelayoutcontroller.cxx
+++ b/sd/source/ui/controller/slidelayoutcontroller.cxx
@@ -132,13 +132,10 @@ static void fillLayoutValueSet( ValueSet* pValue, const snewfoil_value_info_layo
     for( ; pInfo->mpStrResId; pInfo++ )
     {
         OUString aText(SdResId(pInfo->mpStrResId));
-        BitmapEx aBmp(OUString::createFromAscii(pInfo->msBmpResId));
-
-        pValue->InsertItem(static_cast<sal_uInt16>(pInfo->maAutoLayout)+1,
-                Image(aBmp), aText);
-
-        aLayoutItemSize.setWidth( std::max( aLayoutItemSize.Width(),  aBmp.GetSizePixel().Width()  ) );
-        aLayoutItemSize.setHeight( std::max( aLayoutItemSize.Height(), aBmp.GetSizePixel().Height() ) );
+        Image aImg("private:graphicrepository/" + OUString::createFromAscii(pInfo->msBmpResId));
+        pValue->InsertItem(static_cast<sal_uInt16>(pInfo->maAutoLayout)+1, aImg, aText);
+        aLayoutItemSize.setWidth( std::max( aLayoutItemSize.Width(),  aImg.GetSizePixel().Width()  ) );
+        aLayoutItemSize.setHeight( std::max( aLayoutItemSize.Height(), aImg.GetSizePixel().Height() ) );
     }
 
     aLayoutItemSize = pValue->CalcItemSizePixel( aLayoutItemSize );
diff --git a/vcl/inc/image.h b/vcl/inc/image.h
index 1cb0c43cdd72..f966a8c62c1f 100644
--- a/vcl/inc/image.h
+++ b/vcl/inc/image.h
@@ -28,10 +28,25 @@
 struct ImplImage
 {
     BitmapChecksum maBitmapChecksum;
-    BitmapEx const maBitmapEx;
+    /// if non-empty: cached original size of maStockName else Size of maBitmap
+    Size     maSizePixel;
+    /// If set - defines the bitmap via images.zip*
+    OUString maStockName;
+
+    /// Original bitmap - or cache of a potentially scaled bitmap
+    BitmapEx maBitmapEx;
     BitmapEx maDisabledBitmapEx;
 
     ImplImage(const BitmapEx& rBitmapEx);
+    ImplImage(const OUString &aStockName);
+
+    bool isStock() const { return maStockName.getLength() > 0; }
+
+    /// get size in co-ordinates not scaled for HiDPI
+    Size getSizePixel();
+    BitmapEx getBitmapEx(bool bDisabled = false);
+    bool isEqual(const ImplImage &ref) const;
+    bool isSizeEmpty() const { return maSizePixel == Size(0, 0); }
 };
 
 #endif // INCLUDED_VCL_INC_IMAGE_H
diff --git a/vcl/source/control/fixed.cxx b/vcl/source/control/fixed.cxx
index 435c0b6a6a67..f1cb825ad6b2 100644
--- a/vcl/source/control/fixed.cxx
+++ b/vcl/source/control/fixed.cxx
@@ -965,8 +965,7 @@ void FixedImage::SetModeImage( const Image& rImage )
 
 Image FixedImage::loadThemeImage(const OUString &rFileName)
 {
-    BitmapEx aBitmap(rFileName);
-    return Image(aBitmap);
+    return Image("private:graphicrepository/" + rFileName);
 }
 
 bool FixedImage::set_property(const OString &rKey, const OUString &rValue)
diff --git a/vcl/source/image/Image.cxx b/vcl/source/image/Image.cxx
index 049e3bef5d0d..8bce4839a1ea 100644
--- a/vcl/source/image/Image.cxx
+++ b/vcl/source/image/Image.cxx
@@ -58,17 +58,11 @@ Image::Image(const OUString & rFileUrl)
     sal_Int32 nIndex = 0;
     if (rFileUrl.getToken( 0, '/', nIndex ) == "private:graphicrepository")
     {
-        OUString sPathName(rFileUrl.copy(nIndex));
-        BitmapEx aBitmapEx;
-        if (vcl::ImageRepository::loadImage(sPathName, aBitmapEx))
-        {
-            ImplInit(aBitmapEx);
-        }
+        mpImplData.reset(new ImplImage(rFileUrl.copy(nIndex)));
     }
     else
     {
         Graphic aGraphic;
-
         if (ERRCODE_NONE == GraphicFilter::LoadGraphic(rFileUrl, IMP_PNG, aGraphic))
         {
             ImplInit(aGraphic.GetBitmapEx());
@@ -79,33 +73,23 @@ Image::Image(const OUString & rFileUrl)
 void Image::ImplInit(const BitmapEx& rBitmapEx)
 {
     if (!rBitmapEx.IsEmpty())
-    {
         mpImplData.reset(new ImplImage(rBitmapEx));
-    }
 }
 
 Size Image::GetSizePixel() const
 {
-    Size aRet;
-
     if (mpImplData)
-    {
-        aRet = mpImplData->maBitmapEx.GetSizePixel();
-    }
-
-    return aRet;
+        return mpImplData->getSizePixel();
+    else
+        return Size();
 }
 
 BitmapEx Image::GetBitmapEx() const
 {
-    BitmapEx aRet;
-
     if (mpImplData)
-    {
-        aRet = mpImplData->maBitmapEx;
-    }
-
-    return aRet;
+        return mpImplData->getBitmapEx();
+    else
+        return BitmapEx();
 }
 
 bool Image::operator==(const Image& rImage) const
@@ -117,7 +101,7 @@ bool Image::operator==(const Image& rImage) const
     else if (!rImage.mpImplData || !mpImplData)
         bRet = false;
     else
-        bRet = rImage.mpImplData->maBitmapEx == mpImplData->maBitmapEx;
+        bRet = rImage.mpImplData->isEqual(*mpImplData);
 
     return bRet;
 }
@@ -128,63 +112,49 @@ void Image::Draw(OutputDevice* pOutDev, const Point& rPos, DrawImageFlags nStyle
         return;
 
     const Point aSrcPos(0, 0);
-    Size aBitmapSizePixel = mpImplData->maBitmapEx.GetSizePixel();
+    Size aBitmapSizePixel = mpImplData->getSizePixel();
 
     Size aOutSize = pSize ? *pSize : pOutDev->PixelToLogic(aBitmapSizePixel);
 
-    if (nStyle & DrawImageFlags::Disable)
-    {
-        BitmapChecksum aChecksum = mpImplData->maBitmapEx.GetChecksum();
-        if (mpImplData->maBitmapChecksum != aChecksum)
-        {
-            BitmapEx aDisabledBmpEx(mpImplData->maBitmapEx);
-            BitmapFilter::Filter(aDisabledBmpEx, BitmapDisabledImageFilter());
+    // FIXME: do the HiDPI scaling fun here [!] =)
+    BitmapEx aRenderBmp = mpImplData->getBitmapEx(!!(nStyle & DrawImageFlags::Disable));
 
-            mpImplData->maBitmapChecksum = aChecksum;
-            mpImplData->maDisabledBitmapEx = aDisabledBmpEx;
-        }
-        pOutDev->DrawBitmapEx(rPos, aOutSize, aSrcPos, aBitmapSizePixel, mpImplData->maDisabledBitmapEx);
-    }
-    else
+    if (!(nStyle & DrawImageFlags::Disable) &&
+        (nStyle & (DrawImageFlags::ColorTransform | DrawImageFlags::Highlight |
+                   DrawImageFlags::Deactive | DrawImageFlags::SemiTransparent)))
     {
-        if (nStyle & (DrawImageFlags::ColorTransform | DrawImageFlags::Highlight |
-                      DrawImageFlags::Deactive | DrawImageFlags::SemiTransparent))
+        BitmapEx aTempBitmapEx(aRenderBmp);
+
+        if (nStyle & (DrawImageFlags::Highlight | DrawImageFlags::Deactive))
         {
-            BitmapEx aTempBitmapEx(mpImplData->maBitmapEx);
+            const StyleSettings& rSettings = pOutDev->GetSettings().GetStyleSettings();
+            Color aColor;
+            if (nStyle & DrawImageFlags::Highlight)
+                aColor = rSettings.GetHighlightColor();
+            else
+                aColor = rSettings.GetDeactiveColor();
+
+            BitmapFilter::Filter(aTempBitmapEx, BitmapColorizeFilter(aColor));
+        }
 
-            if (nStyle & (DrawImageFlags::Highlight | DrawImageFlags::Deactive))
+        if (nStyle & DrawImageFlags::SemiTransparent)
+        {
+            if (aTempBitmapEx.IsTransparent())
             {
-                const StyleSettings& rSettings = pOutDev->GetSettings().GetStyleSettings();
-                Color aColor;
-                if (nStyle & DrawImageFlags::Highlight)
-                    aColor = rSettings.GetHighlightColor();
-                else
-                    aColor = rSettings.GetDeactiveColor();
-
-                BitmapFilter::Filter(aTempBitmapEx, BitmapColorizeFilter(aColor));
+                Bitmap aAlphaBmp(aTempBitmapEx.GetAlpha().GetBitmap());
+                aAlphaBmp.Adjust(50);
+                aTempBitmapEx = BitmapEx(aTempBitmapEx.GetBitmap(), AlphaMask(aAlphaBmp));
             }
-
-            if (nStyle & DrawImageFlags::SemiTransparent)
+            else
             {
-                if (aTempBitmapEx.IsTransparent())
-                {
-                    Bitmap aAlphaBmp(aTempBitmapEx.GetAlpha().GetBitmap());
-                    aAlphaBmp.Adjust(50);
-                    aTempBitmapEx = BitmapEx(aTempBitmapEx.GetBitmap(), AlphaMask(aAlphaBmp));
-                }
-                else
-                {
-                    sal_uInt8 cErase = 128;
-                    aTempBitmapEx = BitmapEx(aTempBitmapEx.GetBitmap(), AlphaMask(aTempBitmapEx.GetSizePixel(), &cErase));
-                }
+                sal_uInt8 cErase = 128;
+                aTempBitmapEx = BitmapEx(aTempBitmapEx.GetBitmap(), AlphaMask(aTempBitmapEx.GetSizePixel(), &cErase));
             }
-            pOutDev->DrawBitmapEx(rPos, aOutSize, aSrcPos, aTempBitmapEx.GetSizePixel(), aTempBitmapEx);
-        }
-        else
-        {
-            pOutDev->DrawBitmapEx(rPos, aOutSize, aSrcPos, mpImplData->maBitmapEx.GetSizePixel(), mpImplData->maBitmapEx);
         }
+        aRenderBmp = aTempBitmapEx;
     }
+
+    pOutDev->DrawBitmapEx(rPos, aOutSize, aSrcPos, aBitmapSizePixel, aRenderBmp);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/image/ImplImage.cxx b/vcl/source/image/ImplImage.cxx
index 82a2099e8813..471dcb091e3d 100644
--- a/vcl/source/image/ImplImage.cxx
+++ b/vcl/source/image/ImplImage.cxx
@@ -17,6 +17,7 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <sal/log.hxx>
 #include <vcl/outdev.hxx>
 #include <vcl/bitmapex.hxx>
 #include <vcl/alpha.hxx>
@@ -25,15 +26,80 @@
 #include <vcl/virdev.hxx>
 #include <vcl/image.hxx>
 #include <vcl/settings.hxx>
+#include <vcl/BitmapFilter.hxx>
+#include <vcl/ImageTree.hxx>
+#include <vcl/imagerepository.hxx>
+#include <BitmapDisabledImageFilter.hxx>
+#include <comphelper/lok.hxx>
 
 #include <image.h>
 #include <memory>
 
 ImplImage::ImplImage(const BitmapEx &rBitmapEx)
     : maBitmapChecksum(0)
+    , maSizePixel(rBitmapEx.GetSizePixel())
     , maBitmapEx(rBitmapEx)
-    , maDisabledBitmapEx()
 {
 }
 
+ImplImage::ImplImage(const OUString &aStockName)
+    : maBitmapChecksum(0)
+    , maSizePixel(0,0) // defer size lookup
+    , maStockName( aStockName )
+{
+}
+
+Size ImplImage::getSizePixel()
+{
+    Size aRet;
+    if (!isSizeEmpty())
+        aRet = maSizePixel;
+    else if (isStock())
+    {
+        BitmapEx aBitmapEx;
+        if (vcl::ImageRepository::loadImage(maStockName, aBitmapEx))
+        {
+            assert(!maDisabledBitmapEx);
+            assert(maBitmapChecksum == 0);
+            maBitmapEx = aBitmapEx;
+            maSizePixel = aBitmapEx.GetSizePixel();
+            aRet = maSizePixel;
+        }
+        else
+            SAL_WARN("vcl", "Failed to load stock icon " << maStockName);
+    }
+    return aRet;
+}
+
+/// non-HiDPI compatibility method.
+BitmapEx ImplImage::getBitmapEx(bool bDisabled)
+{
+    getSizePixel(); // force load, and at unity scale.
+    if (bDisabled)
+    {
+        // Changed since we last generated this.
+        BitmapChecksum aChecksum = maBitmapEx.GetChecksum();
+        if (maBitmapChecksum != aChecksum ||
+            maDisabledBitmapEx.GetSizePixel() != maBitmapEx.GetSizePixel())
+        {
+            maDisabledBitmapEx = maBitmapEx;
+            BitmapFilter::Filter(maDisabledBitmapEx, BitmapDisabledImageFilter());
+            maBitmapChecksum = aChecksum;
+        }
+        return maDisabledBitmapEx;
+    }
+
+    return maBitmapEx;
+}
+
+bool ImplImage::isEqual(const ImplImage &ref) const
+{
+    if (isStock() != ref.isStock())
+        return false;
+    if (isStock())
+        return maStockName == ref.maStockName;
+    else
+        return maBitmapEx == ref.maBitmapEx;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index e2833756b87e..70a62b10463b 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -658,8 +658,8 @@ VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUStr
                 SAL_WARN_IF(eType != SymbolType::IMAGE, "vcl.layout", "unimplemented symbol type for radiobuttons");
             if (eType == SymbolType::IMAGE)
             {
-                BitmapEx aBitmap(mapStockToImageResource(rImageInfo.m_sStock));
-                Image const aImage(aBitmap);
+                Image const aImage("private:graphicrepository/" +
+                                   mapStockToImageResource(rImageInfo.m_sStock));
                 if (!elem.m_bRadio)
                     pTargetButton->SetModeImage(aImage);
                 else
@@ -703,8 +703,8 @@ VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUStr
         if (eType != SymbolType::IMAGE)
             continue;
 
-        BitmapEx aBitmap(mapStockToImageResource(rImageInfo.m_sStock));
-        const Image aImage(aBitmap);
+        Image const aImage("private:graphicrepository/" +
+                           mapStockToImageResource(rImageInfo.m_sStock));
         pImage->SetImage(aImage);
     }
 
diff --git a/vcl/source/window/msgbox.cxx b/vcl/source/window/msgbox.cxx
index b91f3b2fb973..31307c542a9c 100644
--- a/vcl/source/window/msgbox.cxx
+++ b/vcl/source/window/msgbox.cxx
@@ -37,12 +37,13 @@
 static void ImplInitMsgBoxImageList()
 {
     ImplSVData* pSVData = ImplGetSVData();
-    if (pSVData->maWinData.maMsgBoxImgList.empty())
+    std::vector<Image> &rImages = pSVData->maWinData.maMsgBoxImgList;
+    if (rImages.empty())
     {
-        pSVData->maWinData.maMsgBoxImgList.emplace_back(BitmapEx(SV_RESID_BITMAP_ERRORBOX));
-        pSVData->maWinData.maMsgBoxImgList.emplace_back(BitmapEx(SV_RESID_BITMAP_QUERYBOX));
-        pSVData->maWinData.maMsgBoxImgList.emplace_back(BitmapEx(SV_RESID_BITMAP_WARNINGBOX));
-        pSVData->maWinData.maMsgBoxImgList.emplace_back(BitmapEx(SV_RESID_BITMAP_INFOBOX));
+        rImages.emplace_back(Image("private:graphicrepository/" SV_RESID_BITMAP_ERRORBOX));
+        rImages.emplace_back(Image("private:graphicrepository/" SV_RESID_BITMAP_QUERYBOX));
+        rImages.emplace_back(Image("private:graphicrepository/" SV_RESID_BITMAP_WARNINGBOX));
+        rImages.emplace_back(Image("private:graphicrepository/" SV_RESID_BITMAP_INFOBOX));
     }
 }
 
commit 825fe58f3ab3dcb1d216b9d49e502b6bb7b91771
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Fri Apr 26 20:04:00 2019 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Tue Sep 24 13:58:52 2019 +0100

    lok: disable VCL painting and whole window invalidation.
    
    The reasoning is somewhat complex:
    
    void Window::ImplInvalidateFrameRegion( const vcl::Region* pRegion, InvalidateFlags nFlags )
    
    sets the mnPaintFlags on the mpWindowImpl - and then queues an idle
    paint. This paint in LOK mode does ~nothing - since all rendering is
    tiled, although amazingly it does emit eg. selection callbacks.
    
    However the paint flag - changes the behavior of Window::Update() to
    force a complete window invalidate. This happens, but only rarely -
    when a key-event manages to get into the mainloop before the idle
    paint handler arrives and does nothing (except clear the paint flags).
    
    So - don't do these big invalidations we don't need to in lok mode,
    unless it is for dialogs - which presumably Pranav wanted fixed by
    625087b58f3b7.
    
    Change-Id: I88dda34b8d8bba9c89296d883ad9169fe49a7c5e
    Reviewed-on: https://gerrit.libreoffice.org/71396
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Jan Holesovsky <kendy at collabora.com>

diff --git a/vcl/source/window/paint.cxx b/vcl/source/window/paint.cxx
index 8d3f88e9dfce..a94689cc42ad 100644
--- a/vcl/source/window/paint.cxx
+++ b/vcl/source/window/paint.cxx
@@ -33,6 +33,7 @@
 #include <salframe.hxx>
 #include <svdata.hxx>
 #include <comphelper/lok.hxx>
+#include <comphelper/profilezone.hxx>
 #if HAVE_FEATURE_OPENGL
 #include <vcl/opengl/OpenGLHelper.hxx>
 #endif
@@ -634,6 +635,8 @@ void Window::ImplCallOverlapPaint()
 
 IMPL_LINK_NOARG(Window, ImplHandlePaintHdl, Timer *, void)
 {
+    comphelper::ProfileZone aZone("VCL idle re-paint");
+
     // save paint events until layout is done
     if (IsSystemWindow() && static_cast<const SystemWindow*>(this)->hasPendingLayout())
     {
@@ -655,6 +658,8 @@ IMPL_LINK_NOARG(Window, ImplHandlePaintHdl, Timer *, void)
 
 IMPL_LINK_NOARG(Window, ImplHandleResizeTimerHdl, Timer *, void)
 {
+    comphelper::ProfileZone aZone("VCL idle resize");
+
     if( mpWindowImpl->mbReallyVisible )
     {
         ImplCallResize();
@@ -722,6 +727,7 @@ void Window::ImplInvalidateFrameRegion( const vcl::Region* pRegion, InvalidateFl
             pParent->ImplInvalidateFrameRegion( pChildRegion, nFlags );
         }
     }
+
     if ( !mpWindowImpl->mpFrameData->maPaintIdle.IsActive() )
         mpWindowImpl->mpFrameData->maPaintIdle.Start();
 }
@@ -1324,10 +1330,13 @@ void Window::Update()
          }
 
         pUpdateWindow->ImplCallPaint(nullptr, pUpdateWindow->mpWindowImpl->mnPaintFlags);
-        pUpdateWindow->LogicInvalidate(nullptr);
+
+        if (comphelper::LibreOfficeKit::isActive() && pUpdateWindow->GetParentDialog())
+            pUpdateWindow->LogicInvalidate(nullptr);
 
         if (xWindow->IsDisposed())
            return;
+
         bFlush = true;
     }
 
commit 25793b8c889f78244388f5b46069a9bc1b2f0fde
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Thu May 2 11:14:40 2019 +0200
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Tue Sep 24 13:58:52 2019 +0100

    lok: We changed the (unstable) ABI, but let's allow the older C++ API.
    
    Helps building the Online before the appropriate patch gets merged.
    
    Change-Id: I9983d546bb0cb7fb472806622a0a10e3a4d3ab87
    Reviewed-on: https://gerrit.libreoffice.org/71664
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
    Tested-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index e2ca0902edd7..dd0ad0391643 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -188,7 +188,7 @@ public:
      *
      * @param nWindowid
      */
-    void postWindow(unsigned nWindowId, int nAction, const char* pData)
+    void postWindow(unsigned nWindowId, int nAction, const char* pData = nullptr)
     {
         return mpDoc->pClass->postWindow(mpDoc, nWindowId, nAction, pData);
     }
diff --git a/libreofficekit/qa/tilebench/tilebench.cxx b/libreofficekit/qa/tilebench/tilebench.cxx
index d0fc87283d35..61d337f6c518 100644
--- a/libreofficekit/qa/tilebench/tilebench.cxx
+++ b/libreofficekit/qa/tilebench/tilebench.cxx
@@ -286,7 +286,7 @@ static void testDialog( Document *pDocument, const char *uno_cmd )
     }
 
     aTimes.emplace_back("post close dialog");
-    pDocument->postWindow(nDialogId, LOK_WINDOW_CLOSE, nullptr);
+    pDocument->postWindow(nDialogId, LOK_WINDOW_CLOSE);
     aTimes.emplace_back();
 
     pDocument->destroyView(view);
commit c7a75f85056610256dd4594135f6e851ab34eaf6
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Thu May 9 18:25:22 2019 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Tue Sep 24 13:58:52 2019 +0100

    unipoll: add a --unipoll parameter to gtktiledviewer.
    
    Arguably should be the default. Implementation is a bit cute -
    re-starting the main-loop as a child of a callback from its
    idle handler.
    
    Change-Id: I95e87c8a4ae3de745d7ca1f636859dd1d8deca17
    Reviewed-on: https://gerrit.libreoffice.org/72072
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
index 1de1aa94568d..564c1de137c6 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
@@ -356,9 +356,18 @@ gtv_application_window_load_document(GtvApplicationWindow* window,
     *(priv->m_pRenderingArgs) = *aArgs;
 
     // setup lokdocview
-    window->lokdocview = lok_doc_view_new_from_user_profile(priv->m_pRenderingArgs->m_aLoPath.c_str(),
-                                                            priv->m_pRenderingArgs->m_aUserProfile.empty() ? nullptr : priv->m_pRenderingArgs->m_aUserProfile.c_str(),
-                                                          nullptr, nullptr);
+    const char *pUserProfile = priv->m_pRenderingArgs->m_aUserProfile.empty() ?
+        nullptr : priv->m_pRenderingArgs->m_aUserProfile.c_str();
+
+    window->lokdocview = GTK_WIDGET(
+        g_initable_new(LOK_TYPE_DOC_VIEW, nullptr, nullptr,
+                       "lopath", priv->m_pRenderingArgs->m_aLoPath.c_str(),
+                       "unipoll", priv->m_pRenderingArgs->m_bUnipoll,
+                       "userprofileurl", pUserProfile,
+                       "halign", GTK_ALIGN_CENTER,
+                       "valign", GTK_ALIGN_CENTER,
+                       nullptr));
+
     gtk_container_add(GTK_CONTAINER(window->scrolledwindow), window->lokdocview);
 
     setupDocView(window);
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx
index 748195c5aff0..21508097e077 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx
@@ -24,6 +24,7 @@ struct GtvRenderingArgs
     std::string m_aLoPath;
     std::string m_aUserProfile;
     bool m_bEnableTiledAnnotations;
+    bool m_bUnipoll;
 
     std::string m_aBackgroundColor;
     bool m_bHidePageShadow;
@@ -31,6 +32,7 @@ struct GtvRenderingArgs
 
     GtvRenderingArgs()
         : m_bEnableTiledAnnotations(false),
+          m_bUnipoll(false),
           m_bHidePageShadow(false),
           m_bHideWhiteSpace(false)
         { }
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application.cxx b/libreofficekit/qa/gtktiledviewer/gtv-application.cxx
index cd0a88a85fe2..7481076778eb 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-application.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-application.cxx
@@ -52,6 +52,7 @@ gtv_application_init(GtvApplication* app)
     {
         { "version", 0, 0, G_OPTION_ARG_NONE, nullptr, "Show LOkit version", nullptr },
         { "lo-path", 0, 0, G_OPTION_ARG_STRING, nullptr, "LO path", nullptr },
+        { "unipoll", 0, 0, G_OPTION_ARG_NONE, nullptr, "Enable unified polling loop", nullptr },
         { "user-profile", 0, 0, G_OPTION_ARG_STRING, nullptr, "User profile to use", nullptr },
         { "enable-tiled-annotations", 0, 0, G_OPTION_ARG_NONE, nullptr, "Whether tiled annotations should be enabled", nullptr },
         { "background-color", 0, 0, G_OPTION_ARG_STRING, nullptr, "Background color", nullptr },
@@ -98,11 +99,13 @@ gtv_application_handle_local_options(GApplication* app, GVariantDict* options)
         return 1; // Cannot afford to continue in absence of this param
     }
 
+    if (g_variant_dict_contains(options, "unipoll"))
+        priv->m_pRenderingArgs->m_bUnipoll = true;
+
     if (g_variant_dict_contains(options, "version"))
     {
         if (!priv->m_pRenderingArgs->m_aLoPath.empty())
         {
-            // FIXME: Crashes for some reason
             GtkWidget* pDocView = lok_doc_view_new(priv->m_pRenderingArgs->m_aLoPath.c_str(), nullptr, nullptr);
             const gchar* versionInfo = lok_doc_view_get_version_info(LOK_DOC_VIEW(pDocView));
             if (versionInfo)
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 1d7814e0b5c9..f48916298dbe 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -85,6 +85,7 @@ struct LOKDocViewPrivateImpl
     gboolean m_bInit; // initializeForRendering() has been called
     gboolean m_bCanZoomIn;
     gboolean m_bCanZoomOut;
+    gboolean m_bUnipoll;
     LibreOfficeKit* m_pOffice;
     LibreOfficeKitDocument* m_pDocument;
 
@@ -198,6 +199,7 @@ struct LOKDocViewPrivateImpl
         m_bInit(false),
         m_bCanZoomIn(true),
         m_bCanZoomOut(true),
+        m_bUnipoll(false),
         m_pOffice(nullptr),
         m_pDocument(nullptr),
         lokThreadPool(nullptr),
@@ -287,6 +289,7 @@ enum
     PROP_0,
 
     PROP_LO_PATH,
+    PROP_LO_UNIPOLL,
     PROP_LO_POINTER,
     PROP_USER_PROFILE_URL,
     PROP_DOC_PATH,
@@ -2433,6 +2436,9 @@ static void lok_doc_view_set_property (GObject* object, guint propId, const GVal
     case PROP_LO_PATH:
         priv->m_aLOPath = g_value_get_string (value);
         break;
+    case PROP_LO_UNIPOLL:
+        priv->m_bUnipoll = g_value_get_boolean (value);
+        break;
     case PROP_LO_POINTER:
         priv->m_pOffice = static_cast<LibreOfficeKit*>(g_value_get_pointer(value));
         break;
@@ -2495,6 +2501,9 @@ static void lok_doc_view_get_property (GObject* object, guint propId, GValue *va
     case PROP_LO_PATH:
         g_value_set_string (value, priv->m_aLOPath.c_str());
         break;
+    case PROP_LO_UNIPOLL:
+        g_value_set_boolean (value, priv->m_bUnipoll);
+        break;
     case PROP_LO_POINTER:
         g_value_set_pointer(value, priv->m_pOffice);
         break;
@@ -2620,6 +2629,41 @@ static void lok_doc_view_finalize (GObject* object)
     G_OBJECT_CLASS (lok_doc_view_parent_class)->finalize (object);
 }
 
+// kicks the mainloop awake
+static gboolean timeout_wakeup(void *)
+{
+    return FALSE;
+}
+
+// integrate our mainloop with LOK's
+static int lok_poll_callback(void*, int timeoutUs)
+{
+    if (timeoutUs)
+    {
+        guint timeout = g_timeout_add(timeoutUs / 1000, timeout_wakeup, nullptr);
+        g_main_context_iteration(nullptr, TRUE);
+        g_source_remove(timeout);
+    }
+    else
+        g_main_context_iteration(nullptr, FALSE);
+
+    return 0;
+}
+
+// thread-safe wakeup of our mainloop
+static void lok_wake_callback(void *)
+{
+    g_main_context_wakeup(nullptr);
+}
+
+static gboolean spin_lok_loop(void *pData)
+{
+    LOKDocView *pDocView = LOK_DOC_VIEW (pData);
+    LOKDocViewPrivate& priv = getPrivate(pDocView);
+    priv->m_pOffice->pClass->runLoop(priv->m_pOffice, lok_poll_callback, lok_wake_callback, nullptr);
+    return FALSE;
+}
+
 static gboolean lok_doc_view_initable_init (GInitable *initable, GCancellable* /*cancellable*/, GError **error)
 {
     LOKDocView *pDocView = LOK_DOC_VIEW (initable);
@@ -2628,6 +2672,9 @@ static gboolean lok_doc_view_initable_init (GInitable *initable, GCancellable* /
     if (priv->m_pOffice != nullptr)
         return TRUE;
 
+    if (priv->m_bUnipoll)
+        g_setenv("SAL_LOK_OPTIONS", "unipoll", FALSE);
+
     priv->m_pOffice = lok_init_2(priv->m_aLOPath.c_str(), priv->m_aUserProfileURL.empty() ? nullptr : priv->m_aUserProfileURL.c_str());
 
     if (priv->m_pOffice == nullptr)
@@ -2642,6 +2689,9 @@ static gboolean lok_doc_view_initable_init (GInitable *initable, GCancellable* /
     priv->m_nLOKFeatures |= LOK_FEATURE_VIEWID_IN_VISCURSOR_INVALIDATION_CALLBACK;
     priv->m_pOffice->pClass->setOptionalFeatures(priv->m_pOffice, priv->m_nLOKFeatures);
 
+    if (priv->m_bUnipoll)
+        g_idle_add(spin_lok_loop, pDocView);
+
     return TRUE;
 }
 
@@ -2682,6 +2732,19 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass)
                                                      G_PARAM_STATIC_STRINGS));
 
     /**
+     * LOKDocView:unipoll:
+     *
+     * Whether we use our own unified polling mainloop in place of glib's
+     */
+    properties[PROP_LO_UNIPOLL] =
+        g_param_spec_boolean("unipoll",
+                             "Unified Polling",
+                             "Whether we use a custom unified polling loop",
+                             FALSE,
+                             static_cast<GParamFlags>(G_PARAM_READWRITE |
+                                                      G_PARAM_CONSTRUCT_ONLY |
+                                                      G_PARAM_STATIC_STRINGS));
+    /**
      * LOKDocView:lopointer:
      *
      * A LibreOfficeKit* in case lok_init() is already called
commit caf68cc79e05c2e2e9ff6a535da5562b45596ad1
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Thu Jun 6 17:43:20 2019 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Tue Sep 24 13:58:52 2019 +0100

    lok: remove ext text event re-entrancy hazard.
    
    Change-Id: I7566c158330bab77589d422c61c64210727ab835
    Reviewed-on: https://gerrit.libreoffice.org/73625
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/73756
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/vcl/source/window/winproc.cxx b/vcl/source/window/winproc.cxx
index 3f127e0afd08..99fefdeece20 100644
--- a/vcl/source/window/winproc.cxx
+++ b/vcl/source/window/winproc.cxx
@@ -1137,6 +1137,12 @@ static bool ImplHandleExtTextInput( vcl::Window* pWindow,
         }
         if( !pChild->ImplGetWindowImpl()->mpFrameData->mnFocusId )
             break;
+
+        if (comphelper::LibreOfficeKit::isActive())
+        {
+            SAL_WARN("vcl", "Failed to get ext text input context");
+            break;
+        }
         Application::Yield();
     }
 


More information about the Libreoffice-commits mailing list