Resolves: tdf#63955 clip 19km long line to some sane limit

Change-Id: If9757a5fa2bb93b56b9cf9f566972f687a4a3a45
Reviewed-on: https://gerrit.libreoffice.org/17036
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit d1046e7c3f66e5f3384ee1ef534ef28346702fc6)

refactor ensuring polygon has at least a line in it

just split that out into a standalone function, no logic
change

Change-Id: I061d5d716b3fc2a9fb6385e7fb249ce300752130
(cherry picked from commit 83b3349bb94d4c48db4da8fe5f8fdb9b19e633b9)
Reviewed-on: https://gerrit.libreoffice.org/17074
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
diff --git a/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx b/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx
index 7004342..c44c6a2 100644
--- a/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx
+++ b/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx
@@ -20,13 +20,14 @@

#include <sdr/contact/viewcontactofsdrpathobj.hxx>
#include <svx/svdopath.hxx>
#include <svx/svdpage.hxx>
#include <svx/sdr/primitive2d/sdrattributecreator.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygonclipper.hxx>
#include <sdr/primitive2d/sdrpathprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>



namespace sdr
{
    namespace contact
@@ -40,6 +41,30 @@ namespace sdr
        {
        }

        static sal_uInt32 ensureGeometry(basegfx::B2DPolyPolygon& rUnitPolyPolygon)
        {
            sal_uInt32 nPolyCount(rUnitPolyPolygon.count());
            sal_uInt32 nPointCount(0);

            for(sal_uInt32 a(0); a < nPolyCount; a++)
            {
                nPointCount += rUnitPolyPolygon.getB2DPolygon(a).count();
            }

            if(!nPointCount)
            {
                OSL_FAIL("PolyPolygon object without geometry detected, this should not be created (!)");
                basegfx::B2DPolygon aFallbackLine;
                aFallbackLine.append(basegfx::B2DPoint(0.0, 0.0));
                aFallbackLine.append(basegfx::B2DPoint(1000.0, 1000.0));
                rUnitPolyPolygon = basegfx::B2DPolyPolygon(aFallbackLine);

                nPolyCount = 1;
            }

            return nPolyCount;
        }

        drawinglayer::primitive2d::Primitive2DSequence ViewContactOfSdrPathObj::createViewIndependentPrimitive2DSequence() const
        {
            const SfxItemSet& rItemSet = GetPathObj().GetMergedItemSet();
@@ -54,34 +79,44 @@ namespace sdr
            // to current zoom so as objects relative position to grid
            // appears stable
            aUnitPolyPolygon.transform( basegfx::tools::createTranslateB2DHomMatrix( aGridOff.X(), aGridOff.Y() ) );
            sal_uInt32 nPolyCount(aUnitPolyPolygon.count());
            sal_uInt32 nPointCount(0);

            for(sal_uInt32 a(0); a < nPolyCount; a++)
            {
                nPointCount += aUnitPolyPolygon.getB2DPolygon(a).count();
            }

            if(!nPointCount)
            {
                OSL_FAIL("PolyPolygon object without geometry detected, this should not be created (!)");
                basegfx::B2DPolygon aFallbackLine;
                aFallbackLine.append(basegfx::B2DPoint(0.0, 0.0));
                aFallbackLine.append(basegfx::B2DPoint(1000.0, 1000.0));
                aUnitPolyPolygon = basegfx::B2DPolyPolygon(aFallbackLine);

                nPolyCount = 1;
            }
            sal_uInt32 nPolyCount(ensureGeometry(aUnitPolyPolygon));

            // prepare object transformation and unit polygon (direct model data)
            basegfx::B2DHomMatrix aObjectMatrix;
            const bool bIsLine(
            bool bIsLine(
                !aUnitPolyPolygon.areControlPointsUsed()
                && 1 == nPolyCount
                && 2 == aUnitPolyPolygon.getB2DPolygon(0).count());

            if(bIsLine)
            {
                const SdrPage* pPage = GetPathObj().GetPage();
                if (pPage)
                {
                    //tdf#63955 if we have an extremely long line then clip it
                    //to a very generous range of -1 page width/height vs +1
                    //page width/height to avoid oom and massive churn
                    //generating a huge polygon chain to cover the length in
                    //applyLineDashing if this line is dashed
                    double fPageWidth = pPage->GetWdt();
                    double fPageHeight = pPage->GetHgt();
                    basegfx::B2DRange aClipRange(-fPageWidth, -fPageHeight,
                                                 fPageWidth*2, fPageHeight*2);
                    aUnitPolyPolygon = basegfx::tools::clipPolyPolygonOnRange(aUnitPolyPolygon,
                                                                       aClipRange, true, true);
                    nPolyCount = ensureGeometry(aUnitPolyPolygon);

                    // re-check that we have't been clipped out to oblivion
                    bIsLine =
                        !aUnitPolyPolygon.areControlPointsUsed()
                        && 1 == nPolyCount
                        && 2 == aUnitPolyPolygon.getB2DPolygon(0).count();
                }
            }

            if(bIsLine)
            {

                // special handling for single line mode (2 points)
                const basegfx::B2DPolygon aSubPolygon(aUnitPolyPolygon.getB2DPolygon(0));
                const basegfx::B2DPoint aStart(aSubPolygon.getB2DPoint(0));