[Libreoffice-commits] core.git: include/svx offapi/com offapi/UnoApi_offapi.mk svx/source xmloff/source

Katarina Behrens (via logerrit) logerrit at kemper.freedesktop.org
Fri Oct 25 14:27:48 UTC 2019


 include/svx/svdpage.hxx                  |    1 
 include/svx/unopage.hxx                  |    9 ++
 offapi/UnoApi_offapi.mk                  |    1 
 offapi/com/sun/star/drawing/XShapes3.idl |   43 +++++++++++++
 svx/source/svdraw/svdpage.cxx            |   96 +++++++++++++++++++++++++++++++
 svx/source/unodraw/unopage.cxx           |    7 ++
 xmloff/source/draw/shapeimport.cxx       |   37 +++++++++++
 7 files changed, 192 insertions(+), 2 deletions(-)

New commits:
commit a8b1699ca9c7e8c43eff79467451fd1fcb4fde9b
Author:     Katarina Behrens <Katarina.Behrens at cib.de>
AuthorDate: Mon Jul 1 18:20:02 2019 +0200
Commit:     Katarina Behrens <Katarina.Behrens at cib.de>
CommitDate: Fri Oct 25 16:27:04 2019 +0200

    speed-up shape import if shapes need z-order rearranging
    
    setting z-order individually on each shape and broadcasting is
    O(n^2) (remaining shapes also need reordering) and this is bad
    bad bad for performance
    
    Change-Id: Ic9c9137a097f6ff524192693910f221885f77cc4
    Reviewed-on: https://gerrit.libreoffice.org/75055
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>

diff --git a/include/svx/svdpage.hxx b/include/svx/svdpage.hxx
index 5ab621ccbd4c..60cf0bb49004 100644
--- a/include/svx/svdpage.hxx
+++ b/include/svx/svdpage.hxx
@@ -108,6 +108,7 @@ public:
     bool           IsObjOrdNumsDirty() const        { return mbObjOrdNumsDirty; }
     virtual void   NbcInsertObject(SdrObject* pObj, size_t nPos=SAL_MAX_SIZE);
     virtual void   InsertObject(SdrObject* pObj, size_t nPos=SAL_MAX_SIZE);
+    virtual void sort( std::vector<sal_Int32>& sortOrder );
 
     /// remove from list without delete
     virtual SdrObject* NbcRemoveObject(size_t nObjNum);
diff --git a/include/svx/unopage.hxx b/include/svx/unopage.hxx
index 50b54a62c754..6814f859904a 100644
--- a/include/svx/unopage.hxx
+++ b/include/svx/unopage.hxx
@@ -24,12 +24,13 @@
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/drawing/XDrawPage.hpp>
 #include <com/sun/star/drawing/XShapes2.hpp>
+#include <com/sun/star/drawing/XShapes3.hpp>
 #include <com/sun/star/drawing/XShapeGrouper.hpp>
 #include <com/sun/star/lang/XUnoTunnel.hpp>
 #include <editeng/mutxhelp.hxx>
 #include <svx/svxdllapi.h>
 
-#include <cppuhelper/implbase6.hxx>
+#include <cppuhelper/implbase7.hxx>
 #include <comphelper/servicehelper.hxx>
 
 #include <memory>
@@ -50,9 +51,10 @@ enum class SdrInventor : sal_uInt32;
 #define TWIPS_TO_MM(val) ((val * 127 + 36) / 72)
 #define MM_TO_TWIPS(val) ((val * 72 + 63) / 127)
 
-class SVX_DLLPUBLIC SvxDrawPage : public ::cppu::WeakAggImplHelper6< css::drawing::XDrawPage,
+class SVX_DLLPUBLIC SvxDrawPage : public ::cppu::WeakAggImplHelper7< css::drawing::XDrawPage,
                                                css::drawing::XShapeGrouper,
                                                css::drawing::XShapes2,
+                                               css::drawing::XShapes3,
                                                css::lang::XServiceInfo,
                                                css::lang::XUnoTunnel,
                                                css::lang::XComponent>,
@@ -109,6 +111,9 @@ class SVX_DLLPUBLIC SvxDrawPage : public ::cppu::WeakAggImplHelper6< css::drawin
     virtual void SAL_CALL addTop( const css::uno::Reference< css::drawing::XShape >& xShape ) override;
     virtual void SAL_CALL addBottom( const css::uno::Reference< css::drawing::XShape >& xShape ) override;
 
+    // XShapes3
+    virtual void SAL_CALL sort( const css::uno::Sequence< sal_Int32 >& sortOrder ) override;
+
     // XElementAccess
     virtual css::uno::Type SAL_CALL getElementType() override;
     virtual sal_Bool SAL_CALL hasElements() override;
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 4e36995a7d53..5fa55f8f191d 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -2376,6 +2376,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/drawing,\
 	XShapeMirror \
 	XShapes \
 	XShapes2 \
+	XShapes3 \
 	XSlidePreviewCache \
 	XSlidePreviewCacheListener \
 	XSlideRenderer \
diff --git a/offapi/com/sun/star/drawing/XShapes3.idl b/offapi/com/sun/star/drawing/XShapes3.idl
new file mode 100644
index 000000000000..ebb23e7d3a11
--- /dev/null
+++ b/offapi/com/sun/star/drawing/XShapes3.idl
@@ -0,0 +1,43 @@
+/* -*- 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/.
+ */
+
+#ifndef __com_sun_star_drawing_XShapes3_idl__
+#define __com_sun_star_drawing_XShapes3_idl__
+
+#include <com/sun/star/drawing/XShapes.idl>
+
+module com {  module sun {  module star { module drawing {
+
+/**
+ * Yet another XShapes interface, enables sorting shapes with
+ * some extra attention paid to shapes with textboxes and overall
+ * performance
+ *
+ * @since LibreOffice 6.4
+ */
+interface XShapes3
+{
+    /**
+     * Sort shapes according to given sort order, for perf reason
+     * just rearrange and don't broadcast
+     *
+     * @param desired order of the shapes
+     *
+     * @since LibreOffice 6.4
+     */
+
+    void sort( [in] sequence< long> sortOrder )
+        raises( com::sun::star::lang::IllegalArgumentException );
+};
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/svdraw/svdpage.cxx b/svx/source/svdraw/svdpage.cxx
index ae0a0c3cc1e3..8794c2355dd0 100644
--- a/svx/source/svdraw/svdpage.cxx
+++ b/svx/source/svdraw/svdpage.cxx
@@ -57,6 +57,8 @@
 #include <rtl/strbuf.hxx>
 #include <libxml/xmlwriter.h>
 
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
 using namespace ::com::sun::star;
 
 class SdrObjList::WeakSdrObjectContainerType
@@ -556,6 +558,100 @@ SdrObject* SdrObjList::SetObjectOrdNum(size_t nOldObjNum, size_t nNewObjNum)
     return pObj;
 }
 
+void SdrObjList::sort( std::vector<sal_Int32>& sortOrder)
+{
+    // no negative indexes and indexes larger than maList size are allowed
+    auto it = std::find_if( sortOrder.begin(), sortOrder.end(), [this](const sal_Int32& rIt)
+         { return ( rIt < 0 || static_cast<size_t>(rIt) >= maList.size() ); } );
+    if ( it != sortOrder.end())
+        throw css::lang::IllegalArgumentException("negative index of shape", nullptr, 1);
+
+    // no duplicates
+    std::vector<bool> aNoDuplicates(sortOrder.size(), false);
+    for (size_t i = 0; i < sortOrder.size(); ++i )
+    {
+        size_t idx =  static_cast<size_t>( sortOrder[i] );
+
+        if ( aNoDuplicates[idx] )
+            throw css::lang::IllegalArgumentException("duplicate index of shape", nullptr, 2);
+
+        aNoDuplicates[idx] = true;
+    }
+
+    // example sortOrder [2 0 1]
+    // example maList [T T S T T] ( T T = shape with textbox, S = just a shape )
+    // (shapes at positions 0 and 2 have a textbox)
+
+    std::vector<SdrObject*> aNewList(maList.size());
+    std::set<sal_Int32> aShapesWithTextbox;
+    std::vector<sal_Int32> aIncrements;
+    std::vector<sal_Int32> aDuplicates;
+
+    if ( maList.size() > 1)
+    {
+        for (size_t i = 1; i< maList.size(); ++i)
+        {
+            // if this shape is a textbox, then look at its left neighbour
+            // (shape this textbox is in)
+            // and insert the number of textboxes to the left of it
+            if (maList[i]->IsTextBox())
+              aShapesWithTextbox.insert( i - 1 - aShapesWithTextbox.size() );
+        }
+        // example aShapesWithTextbox [0 2]
+    }
+
+    aIncrements.push_back(0);
+    aDuplicates.push_back(sortOrder[0]);
+
+    // corner case: 1st shape is a textbox, add it twice
+    // otherwise sortOrder loop below will skip it
+    if (aShapesWithTextbox.count(sortOrder[0]) > 0)
+        aDuplicates.push_back(sortOrder[0]);
+
+    for (size_t i = 1; i< sortOrder.size(); ++i)
+    {
+         aDuplicates.push_back(sortOrder[i]);
+
+         if (aShapesWithTextbox.count(sortOrder[i]) > 0)
+         {
+             aIncrements.push_back(aIncrements[i-1] + 1 );
+             aDuplicates.push_back(sortOrder[i]);
+         }
+         else
+         {
+             aIncrements.push_back(aIncrements[i-1]);
+         }
+
+         // example aDuplicates [2 2 0 0 1]
+         // example aIncrements [0 1 1]
+    }
+
+    std::vector<sal_Int32> aNewSortOrder(maList.size());
+    sal_Int32 nPrev = -1;
+    for (size_t i = 0; i< aDuplicates.size(); ++i)
+    {
+        if (nPrev != aDuplicates[i])
+            aNewSortOrder[i] = aDuplicates[i] + aIncrements[aDuplicates[i]];
+        else
+            aNewSortOrder[i] = aNewSortOrder[i-1] + 1;
+
+        nPrev = aDuplicates[i];
+
+        // example aNewSortOrder [3 4 0 1 2]
+    }
+
+    if ( aNewSortOrder.size() !=  maList.size())
+        throw css::lang::IllegalArgumentException("mismatch of no. of shapes", nullptr, 0);
+
+    for (size_t i = 0; i < aNewSortOrder.size(); ++i)
+    {
+        aNewList[i] = maList[ sortOrder[i] ];
+        aNewList[i]->SetOrdNum(i);
+    }
+
+    std::swap(aNewList, maList);
+}
+
 const tools::Rectangle& SdrObjList::GetAllObjSnapRect() const
 {
     if (mbRectsDirty) {
diff --git a/svx/source/unodraw/unopage.cxx b/svx/source/unodraw/unopage.cxx
index 5fca5403d042..28082f35e75f 100644
--- a/svx/source/unodraw/unopage.cxx
+++ b/svx/source/unodraw/unopage.cxx
@@ -27,6 +27,7 @@
 #include <osl/mutex.hxx>
 #include <sfx2/dispatch.hxx>
 #include <comphelper/classids.hxx>
+#include <comphelper/sequence.hxx>
 #include <cppuhelper/supportsservice.hxx>
 
 #include <sfx2/objsh.hxx>
@@ -330,6 +331,12 @@ void SAL_CALL SvxDrawPage::remove( const Reference< drawing::XShape >& xShape )
     mpModel->SetChanged();
 }
 
+void SvxDrawPage::sort( const css::uno::Sequence< sal_Int32 >& sortOrder )
+{
+    auto newOrder = comphelper::sequenceToContainer<std::vector<sal_Int32>>(sortOrder);
+    mpPage->sort(newOrder);
+}
+
 // css::container::XIndexAccess
 sal_Int32 SAL_CALL SvxDrawPage::getCount()
 {
diff --git a/xmloff/source/draw/shapeimport.cxx b/xmloff/source/draw/shapeimport.cxx
index f3a5183b976e..6708e48e73dc 100644
--- a/xmloff/source/draw/shapeimport.cxx
+++ b/xmloff/source/draw/shapeimport.cxx
@@ -23,6 +23,7 @@
 
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/text/PositionLayoutDir.hpp>
+#include <com/sun/star/drawing/XShapes3.hpp>
 
 #include <utility>
 #include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
@@ -795,9 +796,45 @@ void ShapeSortContext::popGroupAndSort()
         while( nCount );
     }
 
+    bool bSorted = std::is_sorted(maZOrderList.begin(), maZOrderList.end(),
+                       [&](const ZOrderHint& rLeft, const ZOrderHint& rRight)
+                       { return rLeft.nShould < rRight.nShould; } );
+
+    if (bSorted)
+        return; // nothin' to do
+
     // sort z-ordered shapes by nShould field
     std::sort(maZOrderList.begin(), maZOrderList.end());
 
+    uno::Reference<drawing::XShapes3> xShapes3(mxShapes, uno::UNO_QUERY);
+    if( xShapes3.is())
+    {
+        uno::Sequence<sal_Int32> aNewOrder(maZOrderList.size() + maUnsortedList.size());
+        sal_Int32 nIndex = 0;
+
+        for (ZOrderHint& rHint : maZOrderList)
+        {
+            // fill in the gaps from unordered list
+            for (vector<ZOrderHint>::iterator aIt = maUnsortedList.begin(); aIt != maUnsortedList.end() && nIndex < rHint.nShould; )
+            {
+                aNewOrder[nIndex++] = (*aIt).nIs;
+                aIt = maUnsortedList.erase(aIt);
+            }
+
+            aNewOrder[nIndex] = rHint.nIs;
+            nIndex++;
+        }
+
+        try
+        {
+            xShapes3->sort(aNewOrder);
+            maZOrderList.clear();
+            return;
+        }
+        catch (const css::lang::IllegalArgumentException& /*e*/)
+        {}
+    }
+
     // this is the current index, all shapes before that
     // index are finished
     sal_Int32 nIndex = 0;


More information about the Libreoffice-commits mailing list