drawinglayer/source/primitive2d/borderlineprimitive2d.cxx  |   15 --
 include/drawinglayer/primitive2d/borderlineprimitive2d.hxx |   12 -
 svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx   |   80 ++++++-------
 3 files changed, 52 insertions(+), 55 deletions(-)

New commits:
commit ef4964a4e598c3c9714cdc18ffa40bcb120dbef6
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Tue May 26 12:29:37 2020 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Tue May 26 15:55:53 2020 +0200

    reduce dynamic_cast usage in an O(N^2) algorithm
    
    When scrolling down in tdf#130431 this is the major CPU cost.
    Move the dynamic_cast out of the loops as much as possible.
    
    Change-Id: I0ea9f457bb17fbdde880f09b059f07dec4b1790b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94858
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>

diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx 
b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
index a5c2a51bc44e..b264e2c028af 100644
--- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
@@ -305,18 +305,11 @@ namespace drawinglayer::primitive2d
         ImplPrimitive2DIDBlock(BorderLinePrimitive2D, 
PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D)
 
         Primitive2DReference tryMergeBorderLinePrimitive2D(
-            const Primitive2DReference& rCandidateA,
-            const Primitive2DReference& rCandidateB)
+            const BorderLinePrimitive2D* pCandidateA,
+            const BorderLinePrimitive2D* pCandidateB)
         {
-            // try to cast to BorderLinePrimitive2D
-            const primitive2d::BorderLinePrimitive2D* pCandidateA = 
dynamic_cast< const primitive2d::BorderLinePrimitive2D* >(rCandidateA.get());
-            const primitive2d::BorderLinePrimitive2D* pCandidateB = 
dynamic_cast< const primitive2d::BorderLinePrimitive2D* >(rCandidateB.get());
-
-            // we need a comparable BorderLinePrimitive2D
-            if(nullptr == pCandidateA || nullptr == pCandidateB)
-            {
-                return Primitive2DReference();
-            }
+            assert(pCandidateA);
+            assert(pCandidateB);
 
             // start of candidate has to match end of this
             if(!pCandidateA->getEnd().equal(pCandidateB->getStart()))
diff --git a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx 
b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx
index 1a3bfa2b1b9b..537f503e5b9b 100644
--- a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx
@@ -81,12 +81,6 @@ public:
     bool operator==(const BorderLine& rBorderLine) const;
 };
 
-/// helper to try to merge two instances of BorderLinePrimitive2D. If it was 
possible,
-/// a merged version is in the returned Primitive2DReference. Lots of 
preconditions
-/// have to be met to allow that, see implementation (and maybe even expand)
-Primitive2DReference DRAWINGLAYER_DLLPUBLIC tryMergeBorderLinePrimitive2D(
-    const Primitive2DReference& rCandidateA, const Primitive2DReference& 
rCandidateB);
-
 /** BorderLinePrimitive2D class
 
     This is the basic primitive to build frames around objects, e.g. tables.
@@ -141,6 +135,12 @@ public:
     virtual sal_uInt32 getPrimitive2DID() const override;
 };
 
+/// helper to try to merge two instances of BorderLinePrimitive2D. If it was 
possible,
+/// a merged version is in the returned Primitive2DReference. Lots of 
preconditions
+/// have to be met to allow that, see implementation (and maybe even expand)
+Primitive2DReference DRAWINGLAYER_DLLPUBLIC tryMergeBorderLinePrimitive2D(
+    const BorderLinePrimitive2D* pCandidateA, const BorderLinePrimitive2D* 
pCandidateB);
+
 } // end of namespace drawinglayer::primitive2d
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx 
b/svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx
index 3c131948579b..9799417209f8 100644
--- a/svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx
+++ b/svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx
@@ -797,51 +797,55 @@ namespace drawinglayer::primitive2d
 
                     for(const auto& aCandidatePartial : aPartial)
                     {
-                        if(aRetval.empty())
-                        {
-                            // no local data yet, just add as 1st entry, done
-                            aRetval.append(aCandidatePartial);
-                        }
-                        else
-                        {
-                            bool bDidMerge(false);
+                        bool bDidMerge(false);
 
+                        // This algorithm is O(N^2) and repeated dynamic_cast 
inside would be quite costly.
+                        // So check first and skip if the primitives aren't 
BorderLinePrimitive2D.
+                        const 
drawinglayer::primitive2d::BorderLinePrimitive2D* candidatePartialAsBorder
+                            = dynamic_cast<const 
drawinglayer::primitive2d::BorderLinePrimitive2D*>(aCandidatePartial.get());
+                        if(candidatePartialAsBorder)
+                        {
                             for(auto& aCandidateRetval : aRetval)
                             {
-                                // try to merge by appending new data to 
existing data
-                                const 
drawinglayer::primitive2d::Primitive2DReference aMergeRetvalPartial(
-                                    
drawinglayer::primitive2d::tryMergeBorderLinePrimitive2D(
-                                        aCandidateRetval,
-                                        aCandidatePartial));
-
-                                if(aMergeRetvalPartial.is())
-                                {
-                                    // could append, replace existing data 
with merged data, done
-                                    aCandidateRetval = aMergeRetvalPartial;
-                                    bDidMerge = true;
-                                    break;
-                                }
-
-                                // try to merge by appending existing data to 
new data
-                                const 
drawinglayer::primitive2d::Primitive2DReference aMergePartialRetval(
-                                    
drawinglayer::primitive2d::tryMergeBorderLinePrimitive2D(
-                                        aCandidatePartial,
-                                        aCandidateRetval));
-
-                                if(aMergePartialRetval.is())
+                                const 
drawinglayer::primitive2d::BorderLinePrimitive2D* candidateRetvalAsBorder
+                                    = dynamic_cast<const 
drawinglayer::primitive2d::BorderLinePrimitive2D*>(aCandidateRetval.get());
+                                if(candidateRetvalAsBorder)
                                 {
-                                    // could append, replace existing data 
with merged data, done
-                                    aCandidateRetval = aMergePartialRetval;
-                                    bDidMerge = true;
-                                    break;
+                                    // try to merge by appending new data to 
existing data
+                                    const 
drawinglayer::primitive2d::Primitive2DReference aMergeRetvalPartial(
+                                        
drawinglayer::primitive2d::tryMergeBorderLinePrimitive2D(
+                                            candidateRetvalAsBorder,
+                                            candidatePartialAsBorder));
+
+                                    if(aMergeRetvalPartial.is())
+                                    {
+                                        // could append, replace existing data 
with merged data, done
+                                        aCandidateRetval = aMergeRetvalPartial;
+                                        bDidMerge = true;
+                                        break;
+                                    }
+
+                                    // try to merge by appending existing data 
to new data
+                                    const 
drawinglayer::primitive2d::Primitive2DReference aMergePartialRetval(
+                                        
drawinglayer::primitive2d::tryMergeBorderLinePrimitive2D(
+                                            candidatePartialAsBorder,
+                                            candidateRetvalAsBorder));
+
+                                    if(aMergePartialRetval.is())
+                                    {
+                                        // could append, replace existing data 
with merged data, done
+                                        aCandidateRetval = aMergePartialRetval;
+                                        bDidMerge = true;
+                                        break;
+                                    }
                                 }
                             }
+                        }
 
-                            if(!bDidMerge)
-                            {
-                                // no merge after checking all existing data, 
append as new segment
-                                aRetval.append(aCandidatePartial);
-                            }
+                        if(!bDidMerge)
+                        {
+                            // no merge after checking all existing data, 
append as new segment
+                            aRetval.append(aCandidatePartial);
                         }
                     }
                 }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to