[Libreoffice-commits] core.git: 2 commits - basegfx/source basegfx/test sc/qa sc/source

Michael Meeks michael.meeks at collabora.com
Wed Jan 1 03:09:28 PST 2014


 basegfx/source/polygon/b2dtrapezoid.cxx |  146 +++++++++++++++++---------------
 basegfx/test/basegfx2d.cxx              |   34 ++++++-
 basegfx/test/boxclipper.cxx             |    3 
 sc/qa/unit/ucalc.cxx                    |   13 ++
 sc/qa/unit/ucalc.hxx                    |    2 
 sc/source/core/data/column.cxx          |    3 
 6 files changed, 131 insertions(+), 70 deletions(-)

New commits:
commit 2528e5d9058dc7b88a55fcc69226161bccec2691
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Jan 1 11:07:46 2014 +0000

    fdo#73021 - avoid call crash on spell-check + unit test.
    
    Change-Id: I3588ef45617bda440f970e54274cc0985b7baed5

diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 17c4123..283f763 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -1639,6 +1639,19 @@ void Test::testEnterMixedMatrix()
     m_pDoc->DeleteTab(0);
 }
 
+void Test::testCellCopy()
+{
+    m_pDoc->InsertTab(0, "TestTab");
+    ScAddress aSrc(0,0,0);
+    ScAddress aDest(0,1,0);
+    OUString aStr("please copy me");
+    m_pDoc->SetString(aSrc, aStr);
+    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetString(aSrc), aStr);
+    // copy to self - why not ?
+    m_pDoc->CopyCellToDocument(aSrc,aDest,*m_pDoc);
+    CPPUNIT_ASSERT_EQUAL(m_pDoc->GetString(aDest), aStr);
+}
+
 void Test::testSheetCopy()
 {
     m_pDoc->InsertTab(0, "TestTab");
diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index 771a044..5cf8306 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -213,6 +213,7 @@ public:
      */
     void testPivotTableDocFunc();
 
+    void testCellCopy();
     void testSheetCopy();
     void testSheetMove();
     void testExternalRef();
@@ -351,6 +352,7 @@ public:
     CPPUNIT_TEST(testPivotTableNumStability);
     CPPUNIT_TEST(testPivotTableFieldReference);
     CPPUNIT_TEST(testPivotTableDocFunc);
+    CPPUNIT_TEST(testCellCopy);
     CPPUNIT_TEST(testSheetCopy);
     CPPUNIT_TEST(testSheetMove);
     CPPUNIT_TEST(testExternalRef);
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 921ff25..e852e1f 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -1564,7 +1564,8 @@ void ScColumn::CopyCellToDocument( SCROW nSrcRow, SCROW nDestRow, ScColumn& rDes
         rDestCol.maCellTextAttrs.set(nDestRow, maCellTextAttrs.get<sc::CellTextAttr>(nSrcRow));
         ScPostIt* pNote = maCellNotes.get<ScPostIt*>(nSrcRow);
         rDestCol.maCellNotes.set(nDestRow, pNote);
-        pNote->UpdateCaptionPos(ScAddress(rDestCol.nCol, nDestRow, rDestCol.nTab));
+        if (pNote)
+            pNote->UpdateCaptionPos(ScAddress(rDestCol.nCol, nDestRow, rDestCol.nTab));
     }
     else
     {
commit 82b56544a7a53528970632d086c3cfd8ef879335
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Jan 1 10:29:40 2014 +0000

    basegfx: accelerate Trapezoid subdivision by avoiding allocations.
    
    Allocate on the stack where possible, then more conservatively on
    the heap. Unit test Trapezoid subdivision for good measure.
    
    Change-Id: I83e63fd55fddcad149bb5279865670ebb18e0ab1

diff --git a/basegfx/source/polygon/b2dtrapezoid.cxx b/basegfx/source/polygon/b2dtrapezoid.cxx
index 2392a7a..275f375 100644
--- a/basegfx/source/polygon/b2dtrapezoid.cxx
+++ b/basegfx/source/polygon/b2dtrapezoid.cxx
@@ -193,6 +193,60 @@ namespace basegfx
 {
     namespace trapezoidhelper
     {
+        // FIXME: templatize this and use it for TrDeEdgeEntries too ...
+
+        /// Class to allow efficient allocation and release of B2DPoints
+        class PointBlockAllocator
+        {
+            static const int nBlockSize = 32;
+            size_t nCurPoint;
+            B2DPoint *mpPointBase;
+            /// Special case the first allocation to avoid it.
+            B2DPoint maFirstStackBlock[nBlockSize];
+            std::vector< B2DPoint * > maBlocks;
+        public:
+            PointBlockAllocator() :
+                nCurPoint( nBlockSize ),
+                mpPointBase( maFirstStackBlock )
+            {
+            }
+
+            ~PointBlockAllocator()
+            {
+                while(maBlocks.size() > 0)
+                {
+                    delete [] maBlocks.back();
+                    maBlocks.pop_back();
+                }
+            }
+
+            B2DPoint *allocatePoint()
+            {
+                if(nCurPoint >= nBlockSize)
+                {
+                    mpPointBase = new B2DPoint[nBlockSize];
+                    maBlocks.push_back(mpPointBase);
+                    nCurPoint = 0;
+                }
+                return mpPointBase + nCurPoint++;
+            }
+
+            B2DPoint *allocatePoint(const B2DTuple &rPoint)
+            {
+                B2DPoint *pPoint = allocatePoint();
+                *pPoint = rPoint;
+                return pPoint;
+            }
+
+            /// This is a very uncommon case but why not ...
+            void freeIfLast(B2DPoint *pPoint)
+            {
+                // just re-use the last point if we can.
+                if ( nCurPoint > 0 && pPoint == mpPointBase + nCurPoint - 1 )
+                    nCurPoint--;
+            }
+        };
+
         // helper class to handle the complete trapezoid subdivision of a PolyPolygon
         class TrapezoidSubdivider
         {
@@ -201,7 +255,8 @@ namespace basegfx
             sal_uInt32                  mnInitialEdgeEntryCount;
             TrDeEdgeEntries             maTrDeEdgeEntries;
             ::std::vector< B2DPoint >   maPoints;
-            ::std::vector< B2DPoint* >  maNewPoints;
+            /// new points allocated for cuts
+            PointBlockAllocator         maNewPoints;
 
             void addEdgeSorted(
                 TrDeEdgeEntries::iterator aCurrent,
@@ -349,22 +404,16 @@ namespace basegfx
                     const double fSimpleLengthB(aDeltaB.getX() + aDeltaB.getY());
                     const bool bAIsLonger(fSimpleLengthA > fSimpleLengthB);
                     B2DPoint* pNewPoint = bAIsLonger
-                        ? new B2DPoint(aEdgeA.getStart() + (fCutA * aDeltaA))
-                        : new B2DPoint(aEdgeB.getStart() + (fCutB * aDeltaB));
-                    bool bRetval(false);
+                        ? maNewPoints.allocatePoint(aEdgeA.getStart() + (fCutA * aDeltaA))
+                        : maNewPoints.allocatePoint(aEdgeB.getStart() + (fCutB * aDeltaB));
+                    bool bRetval = false;
 
                     // try to split both edges
                     bRetval = splitEdgeAtGivenPoint(aEdgeA, *pNewPoint, aCurrent);
                     bRetval |= splitEdgeAtGivenPoint(aEdgeB, *pNewPoint, aCurrent);
 
-                    if(bRetval)
-                    {
-                        maNewPoints.push_back(pNewPoint);
-                    }
-                    else
-                    {
-                        delete pNewPoint;
-                    }
+                    if(!bRetval)
+                        maNewPoints.freeIfLast(pNewPoint);
 
                     return bRetval;
                 }
@@ -419,16 +468,12 @@ namespace basegfx
                                 if(fTools::more(aSplit.getX(), aRange.getMinimum())
                                     && fTools::less(aSplit.getX(), aRange.getMaximum()))
                                 {
-                                    // cut is in XRange of horizontal edge, potenitally needed cut
-                                    B2DPoint* pNewPoint = new B2DPoint(aSplit);
+                                    // cut is in XRange of horizontal edge, potentially needed cut
+                                    B2DPoint* pNewPoint = maNewPoints.allocatePoint(aSplit);
 
-                                    if(splitEdgeAtGivenPoint(aCompare, *pNewPoint, aCurrent))
-                                    {
-                                        maNewPoints.push_back(pNewPoint);
-                                    }
-                                    else
+                                    if(!splitEdgeAtGivenPoint(aCompare, *pNewPoint, aCurrent))
                                     {
-                                        delete pNewPoint;
+                                        maNewPoints.freeIfLast(pNewPoint);
                                     }
                                 }
                             }
@@ -551,17 +596,6 @@ namespace basegfx
                 }
             }
 
-            ~TrapezoidSubdivider()
-            {
-                // delete the extra points created for cuts
-                const sal_uInt32 nCount(maNewPoints.size());
-
-                for(sal_uInt32 a(0); a < nCount; a++)
-                {
-                    delete maNewPoints[a];
-                }
-            }
-
             void Subdivide(B2DTrapezoidVector& ro_Result)
             {
                 // This is the central subdivider. The strategy is to use the first two entries
@@ -671,28 +705,20 @@ namespace basegfx
                         {
                             if(bLeftIsLonger)
                             {
-                                B2DPoint* pNewPoint = new B2DPoint(aLeftEnd);
+                                B2DPoint* pNewPoint = maNewPoints.allocatePoint(aLeftEnd);
 
-                                if(splitEdgeAtGivenPoint(aLeft, *pNewPoint, aCurrent))
+                                if(!splitEdgeAtGivenPoint(aLeft, *pNewPoint, aCurrent))
                                 {
-                                    maNewPoints.push_back(pNewPoint);
-                                }
-                                else
-                                {
-                                    delete pNewPoint;
+                                    maNewPoints.freeIfLast(pNewPoint);
                                 }
                             }
                             else
                             {
-                                B2DPoint* pNewPoint = new B2DPoint(aRightEnd);
+                                B2DPoint* pNewPoint = maNewPoints.allocatePoint(aRightEnd);
 
-                                if(splitEdgeAtGivenPoint(aRight, *pNewPoint, aCurrent))
-                                {
-                                    maNewPoints.push_back(pNewPoint);
-                                }
-                                else
+                                if(!splitEdgeAtGivenPoint(aRight, *pNewPoint, aCurrent))
                                 {
-                                    delete pNewPoint;
+                                    maNewPoints.freeIfLast(pNewPoint);
                                 }
                             }
                         }
@@ -780,28 +806,26 @@ namespace basegfx
                                         aCompare.getStart().getX() <= aSplitRight.getX())
                                     {
                                         // is inside, correct and restart loop
-                                        B2DPoint* pNewLeft = new B2DPoint(aSplitLeft);
+                                        B2DPoint* pNewLeft = maNewPoints.allocatePoint(aSplitLeft);
 
                                         if(splitEdgeAtGivenPoint(aLeft, *pNewLeft, aCurrent))
                                         {
-                                            maNewPoints.push_back(pNewLeft);
                                             bDone = true;
                                         }
                                         else
                                         {
-                                            delete pNewLeft;
+                                            maNewPoints.freeIfLast(pNewLeft);
                                         }
 
-                                        B2DPoint* pNewRight = new B2DPoint(aSplitRight);
+                                        B2DPoint* pNewRight = maNewPoints.allocatePoint(aSplitRight);
 
                                         if(splitEdgeAtGivenPoint(aRight, *pNewRight, aCurrent))
                                         {
-                                            maNewPoints.push_back(pNewRight);
                                             bDone = true;
                                         }
                                         else
                                         {
-                                            delete pNewRight;
+                                            maNewPoints.freeIfLast(pNewRight);
                                         }
                                     }
                                 }
@@ -837,28 +861,20 @@ namespace basegfx
                     {
                         if(bLeftIsLonger)
                         {
-                            B2DPoint* pNewPoint = new B2DPoint(aLeftEnd);
+                            B2DPoint* pNewPoint = maNewPoints.allocatePoint(aLeftEnd);
 
-                            if(splitEdgeAtGivenPoint(aLeft, *pNewPoint, aCurrent))
+                            if(!splitEdgeAtGivenPoint(aLeft, *pNewPoint, aCurrent))
                             {
-                                maNewPoints.push_back(pNewPoint);
-                            }
-                            else
-                            {
-                                delete pNewPoint;
+                                maNewPoints.freeIfLast(pNewPoint);
                             }
                         }
                         else
                         {
-                            B2DPoint* pNewPoint = new B2DPoint(aRightEnd);
+                            B2DPoint* pNewPoint = maNewPoints.allocatePoint(aRightEnd);
 
-                            if(splitEdgeAtGivenPoint(aRight, *pNewPoint, aCurrent))
-                            {
-                                maNewPoints.push_back(pNewPoint);
-                            }
-                            else
+                            if(!splitEdgeAtGivenPoint(aRight, *pNewPoint, aCurrent))
                             {
-                                delete pNewPoint;
+                                maNewPoints.freeIfLast(pNewPoint);
                             }
                         }
                     }
diff --git a/basegfx/test/basegfx2d.cxx b/basegfx/test/basegfx2d.cxx
index 89042cb..afa065c 100644
--- a/basegfx/test/basegfx2d.cxx
+++ b/basegfx/test/basegfx2d.cxx
@@ -30,6 +30,7 @@
 #include <basegfx/polygon/b2dpolypolygontools.hxx>
 #include <basegfx/polygon/b2dpolygonclipper.hxx>
 #include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dtrapezoid.hxx>
 #include <basegfx/range/b2irange.hxx>
 #include <basegfx/range/b2ibox.hxx>
 #include <basegfx/range/b1drange.hxx>
@@ -51,6 +52,7 @@ using namespace ::basegfx;
 
 namespace basegfx2d
 {
+    extern double getRandomOrdinal( const ::std::size_t n );
 
 class b2dsvgdimpex : public CppUnit::TestFixture
 {
@@ -858,13 +860,39 @@ public:
     CPPUNIT_TEST_SUITE_END();
 }; // class b2dpolygontools
 
-
 class b2dpolypolygon : public CppUnit::TestFixture
 {
 public:
     // insert your test code here.
-    void EmptyMethod()
+    void testTrapezoidHelper()
     {
+        B2DPolygon aPolygon;
+        // provoke the PointBlockAllocator to exercise the freeIfLast path
+        for(int i = 0; i < 16 * 10; i++)
+        {
+            B2DPoint aPoint(getRandomOrdinal(1000), getRandomOrdinal(1000));
+            aPolygon.append(aPoint);
+        }
+        // scatter some duplicate points in to stress things more.
+        for(int i = 0; i < 16 * 10; i++)
+        {
+            aPolygon.insert(getRandomOrdinal(aPolygon.count() - 1),
+                            aPolygon.getB2DPoint(getRandomOrdinal(aPolygon.count() - 1)));
+        }
+        B2DPolygon aPolygonOffset;
+        // duplicate the polygon and offset it slightly.
+        for(size_t i = 0; i < aPolygon.count(); i++)
+        {
+            B2DPoint aPoint(aPolygon.getB2DPoint(i));
+            aPoint += B2DPoint(0.5-getRandomOrdinal(1),0.5-getRandomOrdinal(1));
+        }
+        B2DPolyPolygon aPolyPolygon;
+        aPolyPolygon.append(aPolygon);
+        aPolyPolygon.append(aPolygonOffset);
+        B2DTrapezoidVector aVector;
+        basegfx::tools::trapezoidSubdivide(aVector, aPolyPolygon);
+        CPPUNIT_ASSERT_MESSAGE("more than zero sub-divided trapezoids",
+                               aVector.size() > 0);
     }
 
     // Change the following lines only, if you add, remove or rename
@@ -872,7 +900,7 @@ public:
     // because these macros are need by auto register mechanism.
 
     CPPUNIT_TEST_SUITE(b2dpolypolygon);
-    CPPUNIT_TEST(EmptyMethod);
+    CPPUNIT_TEST(testTrapezoidHelper);
     CPPUNIT_TEST_SUITE_END();
 }; // class b2dpolypolygon
 
diff --git a/basegfx/test/boxclipper.cxx b/basegfx/test/boxclipper.cxx
index ddc0a80..9b8bf10 100644
--- a/basegfx/test/boxclipper.cxx
+++ b/basegfx/test/boxclipper.cxx
@@ -38,11 +38,12 @@
 
 using namespace ::basegfx;
 
+extern double getRandomOrdinal( const ::std::size_t n );
 
 namespace basegfx2d
 {
 /// Gets a random ordinal [0,n)
-inline double getRandomOrdinal( const ::std::size_t n )
+double getRandomOrdinal( const ::std::size_t n )
 {
     // use this one when displaying polygons in OOo, which still sucks
     // great rocks when trying to import non-integer svg:d attributes


More information about the Libreoffice-commits mailing list