diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2020-05-26 12:29:37 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2020-05-26 15:55:53 +0200 |
commit | ef4964a4e598c3c9714cdc18ffa40bcb120dbef6 (patch) | |
tree | 9646b70a5b4d90977e0e14a2ce6639de9011cfff /svx | |
parent | 3a93748c9c4faadeb9ab4eb21706d187677549fa (diff) |
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.lunak@collabora.com>
Diffstat (limited to 'svx')
-rw-r--r-- | svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx | 80 |
1 files changed, 42 insertions, 38 deletions
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); } } } |