LCOV - code coverage report
Current view: top level - svx/source/svdraw - svdopath.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 281 1629 17.2 %
Date: 2012-08-25 Functions: 32 113 28.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 306 3198 9.6 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include <tools/bigint.hxx>
      31                 :            : #include <tools/helpers.hxx>
      32                 :            : #include <svx/svdopath.hxx>
      33                 :            : #include <math.h>
      34                 :            : #include <svx/xpool.hxx>
      35                 :            : #include <svx/xpoly.hxx>
      36                 :            : #include <svx/svdattr.hxx>
      37                 :            : #include <svx/svdtrans.hxx>
      38                 :            : #include <svx/svdetc.hxx>
      39                 :            : #include <svx/svddrag.hxx>
      40                 :            : #include <svx/svdmodel.hxx>
      41                 :            : #include <svx/svdpage.hxx>
      42                 :            : #include <svx/svdhdl.hxx>
      43                 :            : #include <svx/svdview.hxx>  // for MovCreate when using curves
      44                 :            : #include "svx/svdglob.hxx"  // Stringcache
      45                 :            : #include "svx/svdstr.hrc"   // the object's name
      46                 :            : 
      47                 :            : #ifdef _MSC_VER
      48                 :            : #pragma optimize ("",off)
      49                 :            : #pragma warning(disable: 4748) // "... because optimizations are disabled ..."
      50                 :            : #endif
      51                 :            : 
      52                 :            : #include <svx/xlnwtit.hxx>
      53                 :            : #include <svx/xlnclit.hxx>
      54                 :            : #include <svx/xflclit.hxx>
      55                 :            : #include <svx/svdogrp.hxx>
      56                 :            : #include <svx/polypolygoneditor.hxx>
      57                 :            : #include <svx/xlntrit.hxx>
      58                 :            : #include <svx/sdr/contact/viewcontactofsdrpathobj.hxx>
      59                 :            : #include <basegfx/matrix/b2dhommatrix.hxx>
      60                 :            : #include "svdconv.hxx"
      61                 :            : #include <basegfx/point/b2dpoint.hxx>
      62                 :            : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      63                 :            : #include <basegfx/range/b2drange.hxx>
      64                 :            : #include <basegfx/curve/b2dcubicbezier.hxx>
      65                 :            : #include <basegfx/polygon/b2dpolygontools.hxx>
      66                 :            : #include <svx/sdr/attribute/sdrtextattribute.hxx>
      67                 :            : #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
      68                 :            : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      69                 :            : #include <svx/sdr/attribute/sdrformtextattribute.hxx>
      70                 :            : 
      71                 :            : using namespace sdr;
      72                 :            : 
      73                 :          0 : inline sal_uInt16 GetPrevPnt(sal_uInt16 nPnt, sal_uInt16 nPntMax, bool bClosed)
      74                 :            : {
      75         [ #  # ]:          0 :     if (nPnt>0) {
      76                 :          0 :         nPnt--;
      77                 :            :     } else {
      78                 :          0 :         nPnt=nPntMax;
      79         [ #  # ]:          0 :         if (bClosed) nPnt--;
      80                 :            :     }
      81                 :          0 :     return nPnt;
      82                 :            : }
      83                 :            : 
      84                 :          0 : inline sal_uInt16 GetNextPnt(sal_uInt16 nPnt, sal_uInt16 nPntMax, bool bClosed)
      85                 :            : {
      86                 :          0 :     nPnt++;
      87 [ #  # ][ #  # ]:          0 :     if (nPnt>nPntMax || (bClosed && nPnt>=nPntMax)) nPnt=0;
                 [ #  # ]
      88                 :          0 :     return nPnt;
      89                 :            : }
      90                 :            : 
      91 [ #  # ][ #  # ]:          0 : struct ImpSdrPathDragData  : public SdrDragStatUserData
      92                 :            : {
      93                 :            :     XPolygon                    aXP;            // section of the original polygon
      94                 :            :     bool                        bValid;         // FALSE = too few points
      95                 :            :     bool                        bClosed;        // closed object?
      96                 :            :     sal_uInt16                      nPoly;          // number of the polygon in the PolyPolygon
      97                 :            :     sal_uInt16                      nPnt;           // number of point in the above polygon
      98                 :            :     sal_uInt16                      nPntAnz;        // number of points of the polygon
      99                 :            :     sal_uInt16                      nPntMax;        // maximum index
     100                 :            :     bool                        bBegPnt;        // dragged point is first point of a Polyline
     101                 :            :     bool                        bEndPnt;        // dragged point is finishing point of a Polyline
     102                 :            :     sal_uInt16                      nPrevPnt;       // index of previous point
     103                 :            :     sal_uInt16                      nNextPnt;       // index of next point
     104                 :            :     bool                        bPrevIsBegPnt;  // previous point is first point of a Polyline
     105                 :            :     bool                        bNextIsEndPnt;  // next point is first point of a Polyline
     106                 :            :     sal_uInt16                      nPrevPrevPnt;   // index of point before previous point
     107                 :            :     sal_uInt16                      nNextNextPnt;   // index of point after next point
     108                 :            :     bool                        bControl;       // point is a control point
     109                 :            :     bool                        bIsPrevControl; // point is a control point before a support point
     110                 :            :     bool                        bIsNextControl; // point is a control point after a support point
     111                 :            :     bool                        bPrevIsControl; // if nPnt is a support point: a control point comes before
     112                 :            :     bool                        bNextIsControl; // if nPnt is a support point: a control point comes after
     113                 :            :     sal_uInt16                      nPrevPrevPnt0;
     114                 :            :     sal_uInt16                      nPrevPnt0;
     115                 :            :     sal_uInt16                      nPnt0;
     116                 :            :     sal_uInt16                      nNextPnt0;
     117                 :            :     sal_uInt16                      nNextNextPnt0;
     118                 :            :     bool                        bEliminate;     // delete point? (is set by MovDrag)
     119                 :            : 
     120                 :            :     sal_Bool                        mbMultiPointDrag;
     121                 :            :     const XPolyPolygon          maOrig;
     122                 :            :     XPolyPolygon                maMove;
     123                 :            :     std::vector<SdrHdl*>        maHandles;
     124                 :            : 
     125                 :            : public:
     126                 :            :     ImpSdrPathDragData(const SdrPathObj& rPO, const SdrHdl& rHdl, sal_Bool bMuPoDr, const SdrDragStat& rDrag);
     127                 :            :     void ResetPoly(const SdrPathObj& rPO);
     128                 :          0 :     sal_Bool IsMultiPointDrag() const { return mbMultiPointDrag; }
     129                 :            : };
     130                 :            : 
     131                 :          0 : ImpSdrPathDragData::ImpSdrPathDragData(const SdrPathObj& rPO, const SdrHdl& rHdl, sal_Bool bMuPoDr, const SdrDragStat& rDrag)
     132                 :            : :   aXP(5),
     133                 :            :     mbMultiPointDrag(bMuPoDr),
     134                 :          0 :     maOrig(rPO.GetPathPoly()),
     135 [ #  # ][ #  # ]:          0 :     maHandles(0)
                 [ #  # ]
     136                 :            : {
     137         [ #  # ]:          0 :     if(mbMultiPointDrag)
     138                 :            :     {
     139                 :          0 :         const SdrMarkView& rMarkView = *rDrag.GetView();
     140                 :          0 :         const SdrHdlList& rHdlList = rMarkView.GetHdlList();
     141                 :          0 :         const sal_uInt32 nHdlCount = rHdlList.GetHdlCount();
     142 [ #  # ][ #  # ]:          0 :         const SdrObject* pInteractionObject(nHdlCount && rHdlList.GetHdl(0) ? rHdlList.GetHdl(0)->GetObj() : 0);
         [ #  # ][ #  # ]
     143                 :            : 
     144         [ #  # ]:          0 :         for(sal_uInt32 a(0); a < nHdlCount; a++)
     145                 :            :         {
     146         [ #  # ]:          0 :             SdrHdl* pTestHdl = rHdlList.GetHdl(a);
     147                 :            : 
     148 [ #  # ][ #  # ]:          0 :             if(pTestHdl && pTestHdl->IsSelected() && pTestHdl->GetObj() == pInteractionObject)
         [ #  # ][ #  # ]
     149                 :            :             {
     150         [ #  # ]:          0 :                 maHandles.push_back(pTestHdl);
     151                 :            :             }
     152                 :            :         }
     153                 :            : 
     154         [ #  # ]:          0 :         maMove = maOrig;
     155                 :          0 :         bValid = sal_True;
     156                 :            :     }
     157                 :            :     else
     158                 :            :     {
     159                 :          0 :         bValid=sal_False;
     160                 :          0 :         bClosed=rPO.IsClosed();          // closed object?
     161                 :          0 :         nPoly=(sal_uInt16)rHdl.GetPolyNum();            // number of the polygon in the PolyPolygon
     162                 :          0 :         nPnt=(sal_uInt16)rHdl.GetPointNum();            // number of points in the above polygon
     163 [ #  # ][ #  # ]:          0 :         const XPolygon aTmpXP(rPO.GetPathPoly().getB2DPolygon(nPoly));
                 [ #  # ]
     164         [ #  # ]:          0 :         nPntAnz=aTmpXP.GetPointCount();        // number of point of the polygon
     165 [ #  # ][ #  # ]:          0 :         if (nPntAnz==0 || (bClosed && nPntAnz==1)) return; // minimum of 1 points for Lines, minimum of 2 points for Polygon
                 [ #  # ]
     166                 :          0 :         nPntMax=nPntAnz-1;                  // maximum index
     167 [ #  # ][ #  # ]:          0 :         bBegPnt=!bClosed && nPnt==0;        // dragged point is first point of a Polyline
     168 [ #  # ][ #  # ]:          0 :         bEndPnt=!bClosed && nPnt==nPntMax;  // dragged point is finishing point of a Polyline
     169 [ #  # ][ #  # ]:          0 :         if (bClosed && nPntAnz<=3) {        // if polygon is only a line
     170 [ #  # ][ #  # ]:          0 :             bBegPnt=(nPntAnz<3) || nPnt==0;
     171 [ #  # ][ #  # ]:          0 :             bEndPnt=(nPntAnz<3) || nPnt==nPntMax-1;
     172                 :            :         }
     173                 :          0 :         nPrevPnt=nPnt;                      // index of previous point
     174                 :          0 :         nNextPnt=nPnt;                      // index of next point
     175         [ #  # ]:          0 :         if (!bBegPnt) nPrevPnt=GetPrevPnt(nPnt,nPntMax,bClosed);
     176         [ #  # ]:          0 :         if (!bEndPnt) nNextPnt=GetNextPnt(nPnt,nPntMax,bClosed);
     177 [ #  # ][ #  # ]:          0 :         bPrevIsBegPnt=bBegPnt || (!bClosed && nPrevPnt==0);
                 [ #  # ]
     178 [ #  # ][ #  # ]:          0 :         bNextIsEndPnt=bEndPnt || (!bClosed && nNextPnt==nPntMax);
                 [ #  # ]
     179                 :          0 :         nPrevPrevPnt=nPnt;                  // index of point before previous point
     180                 :          0 :         nNextNextPnt=nPnt;                  // index of point after next point
     181         [ #  # ]:          0 :         if (!bPrevIsBegPnt) nPrevPrevPnt=GetPrevPnt(nPrevPnt,nPntMax,bClosed);
     182         [ #  # ]:          0 :         if (!bNextIsEndPnt) nNextNextPnt=GetNextPnt(nNextPnt,nPntMax,bClosed);
     183                 :          0 :         bControl=rHdl.IsPlusHdl();          // point is a control point
     184                 :          0 :         bIsPrevControl=sal_False;               // point is a control point before a support point
     185                 :          0 :         bIsNextControl=sal_False;               // point is a control point after a support point
     186                 :          0 :         bPrevIsControl=sal_False;               // if nPnt is a support point: a control point comes before
     187                 :          0 :         bNextIsControl=sal_False;               // if nPnt is a support point: a control point comes after
     188         [ #  # ]:          0 :         if (bControl) {
     189         [ #  # ]:          0 :             bIsPrevControl=aTmpXP.IsControl(nPrevPnt);
     190                 :          0 :             bIsNextControl=!bIsPrevControl;
     191                 :            :         } else {
     192 [ #  # ][ #  # ]:          0 :             bPrevIsControl=!bBegPnt && !bPrevIsBegPnt && aTmpXP.GetFlags(nPrevPnt)==XPOLY_CONTROL;
         [ #  # ][ #  # ]
     193 [ #  # ][ #  # ]:          0 :             bNextIsControl=!bEndPnt && !bNextIsEndPnt && aTmpXP.GetFlags(nNextPnt)==XPOLY_CONTROL;
         [ #  # ][ #  # ]
     194                 :            :         }
     195                 :          0 :         nPrevPrevPnt0=nPrevPrevPnt;
     196                 :          0 :         nPrevPnt0    =nPrevPnt;
     197                 :          0 :         nPnt0        =nPnt;
     198                 :          0 :         nNextPnt0    =nNextPnt;
     199                 :          0 :         nNextNextPnt0=nNextNextPnt;
     200                 :          0 :         nPrevPrevPnt=0;
     201                 :          0 :         nPrevPnt=1;
     202                 :          0 :         nPnt=2;
     203                 :          0 :         nNextPnt=3;
     204                 :          0 :         nNextNextPnt=4;
     205                 :          0 :         bEliminate=sal_False;
     206         [ #  # ]:          0 :         ResetPoly(rPO);
     207 [ #  # ][ #  # ]:          0 :         bValid=sal_True;
     208                 :            :     }
     209                 :            : }
     210                 :            : 
     211                 :          0 : void ImpSdrPathDragData::ResetPoly(const SdrPathObj& rPO)
     212                 :            : {
     213 [ #  # ][ #  # ]:          0 :     const XPolygon aTmpXP(rPO.GetPathPoly().getB2DPolygon(nPoly));
                 [ #  # ]
     214 [ #  # ][ #  # ]:          0 :     aXP[0]=aTmpXP[nPrevPrevPnt0];  aXP.SetFlags(0,aTmpXP.GetFlags(nPrevPrevPnt0));
         [ #  # ][ #  # ]
     215 [ #  # ][ #  # ]:          0 :     aXP[1]=aTmpXP[nPrevPnt0];      aXP.SetFlags(1,aTmpXP.GetFlags(nPrevPnt0));
         [ #  # ][ #  # ]
     216 [ #  # ][ #  # ]:          0 :     aXP[2]=aTmpXP[nPnt0];          aXP.SetFlags(2,aTmpXP.GetFlags(nPnt0));
         [ #  # ][ #  # ]
     217 [ #  # ][ #  # ]:          0 :     aXP[3]=aTmpXP[nNextPnt0];      aXP.SetFlags(3,aTmpXP.GetFlags(nNextPnt0));
         [ #  # ][ #  # ]
     218 [ #  # ][ #  # ]:          0 :     aXP[4]=aTmpXP[nNextNextPnt0];  aXP.SetFlags(4,aTmpXP.GetFlags(nNextNextPnt0));
         [ #  # ][ #  # ]
                 [ #  # ]
     219                 :          0 : }
     220                 :            : 
     221                 :            : /*************************************************************************/
     222                 :            : 
     223                 :            : struct ImpPathCreateUser  : public SdrDragStatUserData
     224                 :            : {
     225                 :            :     Point                   aBezControl0;
     226                 :            :     Point                   aBezStart;
     227                 :            :     Point                   aBezCtrl1;
     228                 :            :     Point                   aBezCtrl2;
     229                 :            :     Point                   aBezEnd;
     230                 :            :     Point                   aCircStart;
     231                 :            :     Point                   aCircEnd;
     232                 :            :     Point                   aCircCenter;
     233                 :            :     Point                   aLineStart;
     234                 :            :     Point                   aLineEnd;
     235                 :            :     Point                   aRectP1;
     236                 :            :     Point                   aRectP2;
     237                 :            :     Point                   aRectP3;
     238                 :            :     long                    nCircRadius;
     239                 :            :     long                    nCircStWink;
     240                 :            :     long                    nCircRelWink;
     241                 :            :     bool                    bBezier;
     242                 :            :     bool                    bBezHasCtrl0;
     243                 :            :     bool                    bCurve;
     244                 :            :     bool                    bCircle;
     245                 :            :     bool                    bAngleSnap;
     246                 :            :     bool                    bLine;
     247                 :            :     bool                    bLine90;
     248                 :            :     bool                    bRect;
     249                 :            :     bool                    bMixedCreate;
     250                 :            :     sal_uInt16                  nBezierStartPoint;
     251                 :            :     SdrObjKind              eStartKind;
     252                 :            :     SdrObjKind              eAktKind;
     253                 :            : 
     254                 :            : public:
     255                 :          0 :     ImpPathCreateUser(): nCircRadius(0),nCircStWink(0),nCircRelWink(0),
     256                 :            :         bBezier(sal_False),bBezHasCtrl0(sal_False),bCurve(sal_False),bCircle(sal_False),bAngleSnap(sal_False),bLine(sal_False),bLine90(sal_False),bRect(sal_False),
     257                 :          0 :         bMixedCreate(sal_False),nBezierStartPoint(0),eStartKind(OBJ_NONE),eAktKind(OBJ_NONE) { }
     258                 :            : 
     259                 :          0 :     void ResetFormFlags() { bBezier=sal_False; bCurve=sal_False; bCircle=sal_False; bLine=sal_False; bRect=sal_False; }
     260 [ #  # ][ #  # ]:          0 :     bool IsFormFlag() const { return bBezier || bCurve || bCircle || bLine || bRect; }
         [ #  # ][ #  # ]
                 [ #  # ]
     261                 :            :     XPolygon GetFormPoly() const;
     262                 :            :     bool CalcBezier(const Point& rP1, const Point& rP2, const Point& rDir, bool bMouseDown);
     263                 :            :     XPolygon GetBezierPoly() const;
     264                 :          0 :     XPolygon GetCurvePoly() const { return XPolygon(); }
     265                 :            :     bool CalcCircle(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView);
     266                 :            :     XPolygon GetCirclePoly() const;
     267                 :            :     bool CalcLine(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView);
     268                 :            :     Point    CalcLine(const Point& rCsr, long nDirX, long nDirY, SdrView* pView) const;
     269                 :            :     XPolygon GetLinePoly() const;
     270                 :            :     bool CalcRect(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView);
     271                 :            :     XPolygon GetRectPoly() const;
     272                 :            : };
     273                 :            : 
     274                 :          0 : XPolygon ImpPathCreateUser::GetFormPoly() const
     275                 :            : {
     276         [ #  # ]:          0 :     if (bBezier) return GetBezierPoly();
     277         [ #  # ]:          0 :     if (bCurve)  return GetCurvePoly();
     278         [ #  # ]:          0 :     if (bCircle) return GetCirclePoly();
     279         [ #  # ]:          0 :     if (bLine)   return GetLinePoly();
     280         [ #  # ]:          0 :     if (bRect)   return GetRectPoly();
     281                 :          0 :     return XPolygon();
     282                 :            : }
     283                 :            : 
     284                 :          0 : bool ImpPathCreateUser::CalcBezier(const Point& rP1, const Point& rP2, const Point& rDir, bool bMouseDown)
     285                 :            : {
     286                 :          0 :     bool bRet = true;
     287                 :          0 :     aBezStart=rP1;
     288                 :          0 :     aBezCtrl1=rP1+rDir;
     289                 :          0 :     aBezCtrl2=rP2;
     290                 :            : 
     291                 :            :     // #i21479#
     292                 :            :     // Also copy the end point when no end point is set yet
     293 [ #  # ][ #  # ]:          0 :     if (!bMouseDown || (0L == aBezEnd.X() && 0L == aBezEnd.Y())) aBezEnd=rP2;
         [ #  # ][ #  # ]
     294                 :            : 
     295                 :          0 :     bBezier=bRet;
     296                 :          0 :     return bRet;
     297                 :            : }
     298                 :            : 
     299                 :          0 : XPolygon ImpPathCreateUser::GetBezierPoly() const
     300                 :            : {
     301                 :          0 :     XPolygon aXP(4);
     302 [ #  # ][ #  # ]:          0 :     aXP[0]=aBezStart; aXP.SetFlags(0,XPOLY_SMOOTH);
     303 [ #  # ][ #  # ]:          0 :     aXP[1]=aBezCtrl1; aXP.SetFlags(1,XPOLY_CONTROL);
     304 [ #  # ][ #  # ]:          0 :     aXP[2]=aBezCtrl2; aXP.SetFlags(2,XPOLY_CONTROL);
     305         [ #  # ]:          0 :     aXP[3]=aBezEnd;
     306                 :          0 :     return aXP;
     307                 :            : }
     308                 :            : 
     309                 :          0 : bool ImpPathCreateUser::CalcCircle(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView)
     310                 :            : {
     311                 :          0 :     long nTangAngle=GetAngle(rDir);
     312                 :          0 :     aCircStart=rP1;
     313                 :          0 :     aCircEnd=rP2;
     314                 :          0 :     aCircCenter=rP1;
     315                 :          0 :     long dx=rP2.X()-rP1.X();
     316                 :          0 :     long dy=rP2.Y()-rP1.Y();
     317         [ #  # ]:          0 :     long dAngle=GetAngle(Point(dx,dy))-nTangAngle;
     318                 :          0 :     dAngle=NormAngle360(dAngle);
     319                 :          0 :     long nTmpAngle=NormAngle360(9000-dAngle);
     320 [ #  # ][ #  # ]:          0 :     bool bRet=nTmpAngle!=9000 && nTmpAngle!=27000;
     321                 :          0 :     long nRad=0;
     322         [ #  # ]:          0 :     if (bRet) {
     323                 :          0 :         double cs=cos(nTmpAngle*nPi180);
     324         [ #  # ]:          0 :         double nR=(double)GetLen(Point(dx,dy))/cs/2;
     325                 :          0 :         nRad=Abs(Round(nR));
     326                 :            :     }
     327         [ #  # ]:          0 :     if (dAngle<18000) {
     328                 :          0 :         nCircStWink=NormAngle360(nTangAngle-9000);
     329                 :          0 :         nCircRelWink=NormAngle360(2*dAngle);
     330                 :          0 :         aCircCenter.X()+=Round(nRad*cos((nTangAngle+9000)*nPi180));
     331                 :          0 :         aCircCenter.Y()-=Round(nRad*sin((nTangAngle+9000)*nPi180));
     332                 :            :     } else {
     333                 :          0 :         nCircStWink=NormAngle360(nTangAngle+9000);
     334                 :          0 :         nCircRelWink=-NormAngle360(36000-2*dAngle);
     335                 :          0 :         aCircCenter.X()+=Round(nRad*cos((nTangAngle-9000)*nPi180));
     336                 :          0 :         aCircCenter.Y()-=Round(nRad*sin((nTangAngle-9000)*nPi180));
     337                 :            :     }
     338 [ #  # ][ #  # ]:          0 :     bAngleSnap=pView!=NULL && pView->IsAngleSnapEnabled();
     339         [ #  # ]:          0 :     if (bAngleSnap) {
     340                 :          0 :         long nSA=pView->GetSnapAngle();
     341         [ #  # ]:          0 :         if (nSA!=0) { // angle snapping
     342                 :          0 :             bool bNeg=nCircRelWink<0;
     343         [ #  # ]:          0 :             if (bNeg) nCircRelWink=-nCircRelWink;
     344                 :          0 :             nCircRelWink+=nSA/2;
     345                 :          0 :             nCircRelWink/=nSA;
     346                 :          0 :             nCircRelWink*=nSA;
     347                 :          0 :             nCircRelWink=NormAngle360(nCircRelWink);
     348         [ #  # ]:          0 :             if (bNeg) nCircRelWink=-nCircRelWink;
     349                 :            :         }
     350                 :            :     }
     351                 :          0 :     nCircRadius=nRad;
     352 [ #  # ][ #  # ]:          0 :     if (nRad==0 || Abs(nCircRelWink)<5) bRet=sal_False;
                 [ #  # ]
     353                 :          0 :     bCircle=bRet;
     354                 :          0 :     return bRet;
     355                 :            : }
     356                 :            : 
     357                 :          0 : XPolygon ImpPathCreateUser::GetCirclePoly() const
     358                 :            : {
     359         [ #  # ]:          0 :     if (nCircRelWink>=0) {
     360                 :            :         XPolygon aXP(aCircCenter,nCircRadius,nCircRadius,
     361         [ #  # ]:          0 :                      sal_uInt16((nCircStWink+5)/10),sal_uInt16((nCircStWink+nCircRelWink+5)/10),sal_False);
     362 [ #  # ][ #  # ]:          0 :         aXP[0]=aCircStart; aXP.SetFlags(0,XPOLY_SMOOTH);
     363 [ #  # ][ #  # ]:          0 :         if (!bAngleSnap) aXP[aXP.GetPointCount()-1]=aCircEnd;
                 [ #  # ]
     364 [ #  # ][ #  # ]:          0 :         return aXP;
     365                 :            :     } else {
     366                 :            :         XPolygon aXP(aCircCenter,nCircRadius,nCircRadius,
     367 [ #  # ][ #  # ]:          0 :                      sal_uInt16(NormAngle360(nCircStWink+nCircRelWink+5)/10),sal_uInt16((nCircStWink+5)/10),sal_False);
     368         [ #  # ]:          0 :         sal_uInt16 nAnz=aXP.GetPointCount();
     369         [ #  # ]:          0 :         for (sal_uInt16 nNum=nAnz/2; nNum>0;) {
     370                 :          0 :             nNum--; // reverse XPoly's order of points
     371                 :          0 :             sal_uInt16 n2=nAnz-nNum-1;
     372         [ #  # ]:          0 :             Point aPt(aXP[nNum]);
     373 [ #  # ][ #  # ]:          0 :             aXP[nNum]=aXP[n2];
     374         [ #  # ]:          0 :             aXP[n2]=aPt;
     375                 :            :         }
     376 [ #  # ][ #  # ]:          0 :         aXP[0]=aCircStart; aXP.SetFlags(0,XPOLY_SMOOTH);
     377 [ #  # ][ #  # ]:          0 :         if (!bAngleSnap) aXP[aXP.GetPointCount()-1]=aCircEnd;
                 [ #  # ]
     378 [ #  # ][ #  # ]:          0 :         return aXP;
     379                 :            :     }
     380                 :            : }
     381                 :            : 
     382                 :          0 : Point ImpPathCreateUser::CalcLine(const Point& aCsr, long nDirX, long nDirY, SdrView* pView) const
     383                 :            : {
     384                 :          0 :     long x=aCsr.X(),x1=x,x2=x;
     385                 :          0 :     long y=aCsr.Y(),y1=y,y2=y;
     386                 :          0 :     bool bHLin=nDirY==0;
     387                 :          0 :     bool bVLin=nDirX==0;
     388         [ #  # ]:          0 :     if (bHLin) y=0;
     389         [ #  # ]:          0 :     else if (bVLin) x=0;
     390                 :            :     else {
     391                 :          0 :         x1=BigMulDiv(y,nDirX,nDirY);
     392                 :          0 :         y2=BigMulDiv(x,nDirY,nDirX);
     393                 :          0 :         long l1=Abs(x1)+Abs(y1);
     394                 :          0 :         long l2=Abs(x2)+Abs(y2);
     395 [ #  # ][ #  # ]:          0 :         if ((l1<=l2) != (pView!=NULL && pView->IsBigOrtho())) {
                 [ #  # ]
     396                 :          0 :             x=x1; y=y1;
     397                 :            :         } else {
     398                 :          0 :             x=x2; y=y2;
     399                 :            :         }
     400                 :            :     }
     401                 :          0 :     return Point(x,y);
     402                 :            : }
     403                 :            : 
     404                 :          0 : bool ImpPathCreateUser::CalcLine(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView)
     405                 :            : {
     406                 :          0 :     aLineStart=rP1;
     407                 :          0 :     aLineEnd=rP2;
     408                 :          0 :     bLine90=sal_False;
     409 [ #  # ][ #  # ]:          0 :     if (rP1==rP2 || (rDir.X()==0 && rDir.Y()==0)) { bLine=sal_False; return sal_False; }
         [ #  # ][ #  # ]
     410                 :          0 :     Point aTmpPt(rP2-rP1);
     411                 :          0 :     long nDirX=rDir.X();
     412                 :          0 :     long nDirY=rDir.Y();
     413         [ #  # ]:          0 :     Point aP1(CalcLine(aTmpPt, nDirX, nDirY,pView)); aP1-=aTmpPt; long nQ1=Abs(aP1.X())+Abs(aP1.Y());
     414         [ #  # ]:          0 :     Point aP2(CalcLine(aTmpPt, nDirY,-nDirX,pView)); aP2-=aTmpPt; long nQ2=Abs(aP2.X())+Abs(aP2.Y());
     415 [ #  # ][ #  # ]:          0 :     if (pView!=NULL && pView->IsOrtho()) nQ1=0; // Ortho turns off at right angle
                 [ #  # ]
     416                 :          0 :     bLine90=nQ1>2*nQ2;
     417         [ #  # ]:          0 :     if (!bLine90) { // smooth transition
     418                 :          0 :         aLineEnd+=aP1;
     419                 :            :     } else {          // rectangular transition
     420                 :          0 :         aLineEnd+=aP2;
     421                 :            :     }
     422                 :          0 :     bLine=sal_True;
     423                 :          0 :     return sal_True;
     424                 :            : }
     425                 :            : 
     426                 :          0 : XPolygon ImpPathCreateUser::GetLinePoly() const
     427                 :            : {
     428                 :          0 :     XPolygon aXP(2);
     429 [ #  # ][ #  # ]:          0 :     aXP[0]=aLineStart; if (!bLine90) aXP.SetFlags(0,XPOLY_SMOOTH);
                 [ #  # ]
     430         [ #  # ]:          0 :     aXP[1]=aLineEnd;
     431                 :          0 :     return aXP;
     432                 :            : }
     433                 :            : 
     434                 :          0 : bool ImpPathCreateUser::CalcRect(const Point& rP1, const Point& rP2, const Point& rDir, SdrView* pView)
     435                 :            : {
     436                 :          0 :     aRectP1=rP1;
     437                 :          0 :     aRectP2=rP1;
     438                 :          0 :     aRectP3=rP2;
     439 [ #  # ][ #  # ]:          0 :     if (rP1==rP2 || (rDir.X()==0 && rDir.Y()==0)) { bRect=sal_False; return sal_False; }
         [ #  # ][ #  # ]
     440                 :          0 :     Point aTmpPt(rP2-rP1);
     441                 :          0 :     long nDirX=rDir.X();
     442                 :          0 :     long nDirY=rDir.Y();
     443                 :          0 :     long x=aTmpPt.X();
     444                 :          0 :     long y=aTmpPt.Y();
     445                 :          0 :     bool bHLin=nDirY==0;
     446                 :          0 :     bool bVLin=nDirX==0;
     447         [ #  # ]:          0 :     if (bHLin) y=0;
     448         [ #  # ]:          0 :     else if (bVLin) x=0;
     449                 :            :     else {
     450         [ #  # ]:          0 :         y=BigMulDiv(x,nDirY,nDirX);
     451                 :          0 :         long nHypLen=aTmpPt.Y()-y;
     452         [ #  # ]:          0 :         long nTangAngle=-GetAngle(rDir);
     453                 :            :         // sin=g/h, g=h*sin
     454                 :          0 :         double a=nTangAngle*nPi180;
     455                 :          0 :         double sn=sin(a);
     456                 :          0 :         double cs=cos(a);
     457                 :          0 :         double nGKathLen=nHypLen*sn;
     458                 :          0 :         y+=Round(nGKathLen*sn);
     459                 :          0 :         x+=Round(nGKathLen*cs);
     460                 :            :     }
     461                 :          0 :     aRectP2.X()+=x;
     462                 :          0 :     aRectP2.Y()+=y;
     463 [ #  # ][ #  # ]:          0 :     if (pView!=NULL && pView->IsOrtho()) {
                 [ #  # ]
     464                 :          0 :         long dx1=aRectP2.X()-aRectP1.X(); long dx1a=Abs(dx1);
     465                 :          0 :         long dy1=aRectP2.Y()-aRectP1.Y(); long dy1a=Abs(dy1);
     466                 :          0 :         long dx2=aRectP3.X()-aRectP2.X(); long dx2a=Abs(dx2);
     467                 :          0 :         long dy2=aRectP3.Y()-aRectP2.Y(); long dy2a=Abs(dy2);
     468                 :          0 :         bool b1MoreThan2=dx1a+dy1a>dx2a+dy2a;
     469         [ #  # ]:          0 :         if (b1MoreThan2 != pView->IsBigOrtho()) {
     470         [ #  # ]:          0 :             long xtemp=dy2a-dx1a; if (dx1<0) xtemp=-xtemp;
     471         [ #  # ]:          0 :             long ytemp=dx2a-dy1a; if (dy1<0) ytemp=-ytemp;
     472                 :          0 :             aRectP2.X()+=xtemp;
     473                 :          0 :             aRectP2.Y()+=ytemp;
     474                 :          0 :             aRectP3.X()+=xtemp;
     475                 :          0 :             aRectP3.Y()+=ytemp;
     476                 :            :         } else {
     477         [ #  # ]:          0 :             long xtemp=dy1a-dx2a; if (dx2<0) xtemp=-xtemp;
     478         [ #  # ]:          0 :             long ytemp=dx1a-dy2a; if (dy2<0) ytemp=-ytemp;
     479                 :          0 :             aRectP3.X()+=xtemp;
     480                 :          0 :             aRectP3.Y()+=ytemp;
     481                 :            :         }
     482                 :            :     }
     483                 :          0 :     bRect=sal_True;
     484                 :          0 :     return sal_True;
     485                 :            : }
     486                 :            : 
     487                 :          0 : XPolygon ImpPathCreateUser::GetRectPoly() const
     488                 :            : {
     489                 :          0 :     XPolygon aXP(3);
     490 [ #  # ][ #  # ]:          0 :     aXP[0]=aRectP1; aXP.SetFlags(0,XPOLY_SMOOTH);
     491         [ #  # ]:          0 :     aXP[1]=aRectP2;
     492 [ #  # ][ #  # ]:          0 :     if (aRectP3!=aRectP2) aXP[2]=aRectP3;
     493                 :          0 :     return aXP;
     494                 :            : }
     495                 :            : 
     496                 :            : /*************************************************************************/
     497                 :            : 
     498                 :            : class ImpPathForDragAndCreate
     499                 :            : {
     500                 :            :     SdrPathObj&                 mrSdrPathObject;
     501                 :            :     XPolyPolygon                aPathPolygon;
     502                 :            :     SdrObjKind                  meObjectKind;
     503                 :            :     ImpSdrPathDragData*         mpSdrPathDragData;
     504                 :            :     bool                        mbCreating;
     505                 :            : 
     506                 :            : public:
     507                 :            :     ImpPathForDragAndCreate(SdrPathObj& rSdrPathObject);
     508                 :            :     ~ImpPathForDragAndCreate();
     509                 :            : 
     510                 :            :     // drag stuff
     511                 :            :     bool beginPathDrag( SdrDragStat& rDrag )  const;
     512                 :            :     bool movePathDrag( SdrDragStat& rDrag ) const;
     513                 :            :     bool endPathDrag( SdrDragStat& rDrag );
     514                 :            :     String getSpecialDragComment(const SdrDragStat& rDrag) const;
     515                 :            :     basegfx::B2DPolyPolygon getSpecialDragPoly(const SdrDragStat& rDrag) const;
     516                 :            : 
     517                 :            :     // create stuff
     518                 :            :     bool BegCreate(SdrDragStat& rStat);
     519                 :            :     bool MovCreate(SdrDragStat& rStat);
     520                 :            :     bool EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd);
     521                 :            :     bool BckCreate(SdrDragStat& rStat);
     522                 :            :     void BrkCreate(SdrDragStat& rStat);
     523                 :            :     Pointer GetCreatePointer() const;
     524                 :            : 
     525                 :            :     // helping stuff
     526 [ #  # ][ #  # ]:          0 :     bool IsClosed(SdrObjKind eKind) const { return eKind==OBJ_POLY || eKind==OBJ_PATHPOLY || eKind==OBJ_PATHFILL || eKind==OBJ_FREEFILL || eKind==OBJ_SPLNFILL; }
         [ #  # ][ #  # ]
                 [ #  # ]
     527 [ #  # ][ #  # ]:          0 :     bool IsFreeHand(SdrObjKind eKind) const { return eKind==OBJ_FREELINE || eKind==OBJ_FREEFILL; }
     528 [ #  # ][ #  # ]:          0 :     bool IsBezier(SdrObjKind eKind) const { return eKind==OBJ_PATHLINE || eKind==OBJ_PATHFILL; }
     529                 :          0 :     bool IsCreating() const { return mbCreating; }
     530                 :            : 
     531                 :            :     // get the polygon
     532                 :            :     basegfx::B2DPolyPolygon TakeObjectPolyPolygon(const SdrDragStat& rDrag) const;
     533                 :            :     basegfx::B2DPolyPolygon TakeDragPolyPolygon(const SdrDragStat& rDrag) const;
     534                 :          0 :     basegfx::B2DPolyPolygon getModifiedPolyPolygon() const { return  aPathPolygon.getB2DPolyPolygon(); }
     535                 :            : };
     536                 :            : 
     537                 :          0 : ImpPathForDragAndCreate::ImpPathForDragAndCreate(SdrPathObj& rSdrPathObject)
     538                 :            : :   mrSdrPathObject(rSdrPathObject),
     539                 :          0 :     aPathPolygon(rSdrPathObject.GetPathPoly()),
     540                 :            :     meObjectKind(mrSdrPathObject.meKind),
     541                 :            :     mpSdrPathDragData(0),
     542                 :          0 :     mbCreating(false)
     543                 :            : {
     544                 :          0 : }
     545                 :            : 
     546                 :          0 : ImpPathForDragAndCreate::~ImpPathForDragAndCreate()
     547                 :            : {
     548         [ #  # ]:          0 :     if(mpSdrPathDragData)
     549                 :            :     {
     550 [ #  # ][ #  # ]:          0 :         delete mpSdrPathDragData;
     551                 :            :     }
     552                 :          0 : }
     553                 :            : 
     554                 :          0 : bool ImpPathForDragAndCreate::beginPathDrag( SdrDragStat& rDrag )  const
     555                 :            : {
     556                 :          0 :     const SdrHdl* pHdl=rDrag.GetHdl();
     557         [ #  # ]:          0 :     if(!pHdl)
     558                 :          0 :         return sal_False;
     559                 :            : 
     560                 :          0 :     sal_Bool bMultiPointDrag(sal_True);
     561                 :            : 
     562         [ #  # ]:          0 :     if(aPathPolygon[(sal_uInt16)pHdl->GetPolyNum()].IsControl((sal_uInt16)pHdl->GetPointNum()))
     563                 :          0 :         bMultiPointDrag = sal_False;
     564                 :            : 
     565         [ #  # ]:          0 :     if(bMultiPointDrag)
     566                 :            :     {
     567                 :          0 :         const SdrMarkView& rMarkView = *rDrag.GetView();
     568                 :          0 :         const SdrHdlList& rHdlList = rMarkView.GetHdlList();
     569                 :          0 :         const sal_uInt32 nHdlCount = rHdlList.GetHdlCount();
     570 [ #  # ][ #  # ]:          0 :         const SdrObject* pInteractionObject(nHdlCount && rHdlList.GetHdl(0) ? rHdlList.GetHdl(0)->GetObj() : 0);
     571                 :          0 :         sal_uInt32 nSelectedPoints(0);
     572                 :            : 
     573         [ #  # ]:          0 :         for(sal_uInt32 a(0); a < nHdlCount; a++)
     574                 :            :         {
     575                 :          0 :             SdrHdl* pTestHdl = rHdlList.GetHdl(a);
     576                 :            : 
     577 [ #  # ][ #  # ]:          0 :             if(pTestHdl && pTestHdl->IsSelected() && pTestHdl->GetObj() == pInteractionObject)
         [ #  # ][ #  # ]
     578                 :            :             {
     579                 :          0 :                 nSelectedPoints++;
     580                 :            :             }
     581                 :            :         }
     582                 :            : 
     583         [ #  # ]:          0 :         if(nSelectedPoints <= 1)
     584                 :          0 :             bMultiPointDrag = sal_False;
     585                 :            :     }
     586                 :            : 
     587         [ #  # ]:          0 :     ((ImpPathForDragAndCreate*)this)->mpSdrPathDragData = new ImpSdrPathDragData(mrSdrPathObject,*pHdl,bMultiPointDrag,rDrag);
     588                 :            : 
     589 [ #  # ][ #  # ]:          0 :     if(!mpSdrPathDragData || !mpSdrPathDragData->bValid)
     590                 :            :     {
     591                 :            :         OSL_FAIL("ImpPathForDragAndCreate::BegDrag(): ImpSdrPathDragData is invalid.");
     592         [ #  # ]:          0 :         delete mpSdrPathDragData;
     593                 :          0 :         ((ImpPathForDragAndCreate*)this)->mpSdrPathDragData = 0;
     594                 :          0 :         return false;
     595                 :            :     }
     596                 :            : 
     597                 :          0 :     return true;
     598                 :            : }
     599                 :            : 
     600                 :          0 : bool ImpPathForDragAndCreate::movePathDrag( SdrDragStat& rDrag ) const
     601                 :            : {
     602 [ #  # ][ #  # ]:          0 :     if(!mpSdrPathDragData || !mpSdrPathDragData->bValid)
     603                 :            :     {
     604                 :            :         OSL_FAIL("ImpPathForDragAndCreate::MovDrag(): ImpSdrPathDragData is invalid.");
     605                 :          0 :         return false;
     606                 :            :     }
     607                 :            : 
     608         [ #  # ]:          0 :     if(mpSdrPathDragData->IsMultiPointDrag())
     609                 :            :     {
     610 [ #  # ][ #  # ]:          0 :         Point aDelta(rDrag.GetNow() - rDrag.GetStart());
     611                 :            : 
     612 [ #  # ][ #  # ]:          0 :         if(aDelta.X() || aDelta.Y())
                 [ #  # ]
     613                 :            :         {
     614         [ #  # ]:          0 :             for(sal_uInt32 a(0); a < mpSdrPathDragData->maHandles.size(); a++)
     615                 :            :             {
     616         [ #  # ]:          0 :                 SdrHdl* pHandle = mpSdrPathDragData->maHandles[a];
     617                 :          0 :                 const sal_uInt16 nPolyIndex((sal_uInt16)pHandle->GetPolyNum());
     618                 :          0 :                 const sal_uInt16 nPointIndex((sal_uInt16)pHandle->GetPointNum());
     619         [ #  # ]:          0 :                 const XPolygon& rOrig = mpSdrPathDragData->maOrig[nPolyIndex];
     620         [ #  # ]:          0 :                 XPolygon& rMove = mpSdrPathDragData->maMove[nPolyIndex];
     621         [ #  # ]:          0 :                 const sal_uInt16 nPointCount(rOrig.GetPointCount());
     622 [ #  # ][ #  # ]:          0 :                 sal_Bool bClosed(rOrig[0] == rOrig[nPointCount-1]);
     623                 :            : 
     624                 :            :                 // move point itself
     625 [ #  # ][ #  # ]:          0 :                 rMove[nPointIndex] = rOrig[nPointIndex] + aDelta;
     626                 :            : 
     627                 :            :                 // when point is first and poly closed, move close point, too.
     628 [ #  # ][ #  # ]:          0 :                 if(nPointCount > 0 && !nPointIndex && bClosed)
                 [ #  # ]
     629                 :            :                 {
     630 [ #  # ][ #  # ]:          0 :                     rMove[nPointCount - 1] = rOrig[nPointCount - 1] + aDelta;
     631                 :            : 
     632                 :            :                     // when moving the last point it may be necessary to move the
     633                 :            :                     // control point in front of this one, too.
     634 [ #  # ][ #  # ]:          0 :                     if(nPointCount > 1 && rOrig.IsControl(nPointCount - 2))
         [ #  # ][ #  # ]
     635 [ #  # ][ #  # ]:          0 :                         rMove[nPointCount - 2] = rOrig[nPointCount - 2] + aDelta;
     636                 :            :                 }
     637                 :            : 
     638                 :            :                 // is a control point before this?
     639 [ #  # ][ #  # ]:          0 :                 if(nPointIndex > 0 && rOrig.IsControl(nPointIndex - 1))
         [ #  # ][ #  # ]
     640                 :            :                 {
     641                 :            :                     // Yes, move it, too
     642 [ #  # ][ #  # ]:          0 :                     rMove[nPointIndex - 1] = rOrig[nPointIndex - 1] + aDelta;
     643                 :            :                 }
     644                 :            : 
     645                 :            :                 // is a control point after this?
     646 [ #  # ][ #  # ]:          0 :                 if(nPointIndex + 1 < nPointCount && rOrig.IsControl(nPointIndex + 1))
         [ #  # ][ #  # ]
     647                 :            :                 {
     648                 :            :                     // Yes, move it, too
     649 [ #  # ][ #  # ]:          0 :                     rMove[nPointIndex + 1] = rOrig[nPointIndex + 1] + aDelta;
     650                 :            :                 }
     651                 :            :             }
     652                 :            :         }
     653                 :            :     }
     654                 :            :     else
     655                 :            :     {
     656         [ #  # ]:          0 :         mpSdrPathDragData->ResetPoly(mrSdrPathObject);
     657                 :            : 
     658                 :            :         // copy certain data locally to use less code and have faster access times
     659                 :          0 :         bool bClosed           =mpSdrPathDragData->bClosed       ; // closed object?
     660                 :          0 :         sal_uInt16   nPnt          =mpSdrPathDragData->nPnt          ; // number of point in the above polygon
     661                 :          0 :         bool bBegPnt           =mpSdrPathDragData->bBegPnt       ; // dragged point is first point of a Polyline
     662                 :          0 :         bool bEndPnt           =mpSdrPathDragData->bEndPnt       ; // dragged point is last point of a Polyline
     663                 :          0 :         sal_uInt16   nPrevPnt      =mpSdrPathDragData->nPrevPnt      ; // index of previous point
     664                 :          0 :         sal_uInt16   nNextPnt      =mpSdrPathDragData->nNextPnt      ; // index of next point
     665                 :          0 :         bool bPrevIsBegPnt     =mpSdrPathDragData->bPrevIsBegPnt ; // previous point is first point of a Polyline
     666                 :          0 :         bool bNextIsEndPnt     =mpSdrPathDragData->bNextIsEndPnt ; // next point is last point of a Polyline
     667                 :          0 :         sal_uInt16   nPrevPrevPnt  =mpSdrPathDragData->nPrevPrevPnt  ; // index of the point before the previous point
     668                 :          0 :         sal_uInt16   nNextNextPnt  =mpSdrPathDragData->nNextNextPnt  ; // index if the point after the next point
     669                 :          0 :         bool bControl          =mpSdrPathDragData->bControl      ; // point is a control point
     670                 :          0 :         bool bIsNextControl    =mpSdrPathDragData->bIsNextControl; // point is a control point after a support point
     671                 :          0 :         bool bPrevIsControl    =mpSdrPathDragData->bPrevIsControl; // if nPnt is a support point: there's a control point before
     672                 :          0 :         bool bNextIsControl    =mpSdrPathDragData->bNextIsControl; // if nPnt is a support point: there's a control point after
     673                 :            : 
     674                 :            :         // Ortho for lines/polygons: keep angle
     675 [ #  # ][ #  # ]:          0 :         if (!bControl && rDrag.GetView()!=NULL && rDrag.GetView()->IsOrtho()) {
         [ #  # ][ #  # ]
     676                 :          0 :             bool bBigOrtho=rDrag.GetView()->IsBigOrtho();
     677         [ #  # ]:          0 :             Point  aPos(rDrag.GetNow());      // current position
     678         [ #  # ]:          0 :             Point  aPnt(mpSdrPathDragData->aXP[nPnt]);      // the dragged point
     679                 :          0 :             sal_uInt16 nPnt1=0xFFFF,nPnt2=0xFFFF; // its neighboring points
     680                 :          0 :             Point  aNeuPos1,aNeuPos2;         // new alternative for aPos
     681                 :          0 :             bool bPnt1 = false, bPnt2 = false; // are these valid alternatives?
     682 [ #  # ][ #  # ]:          0 :             if (!bClosed && mpSdrPathDragData->nPntAnz>=2) { // minimum of 2 points for lines
     683         [ #  # ]:          0 :                 if (!bBegPnt) nPnt1=nPrevPnt;
     684         [ #  # ]:          0 :                 if (!bEndPnt) nPnt2=nNextPnt;
     685                 :            :             }
     686 [ #  # ][ #  # ]:          0 :             if (bClosed && mpSdrPathDragData->nPntAnz>=3) { // minimum of 3 points for polygon
     687                 :          0 :                 nPnt1=nPrevPnt;
     688                 :          0 :                 nPnt2=nNextPnt;
     689                 :            :             }
     690 [ #  # ][ #  # ]:          0 :             if (nPnt1!=0xFFFF && !bPrevIsControl) {
     691         [ #  # ]:          0 :                 Point aPnt1=mpSdrPathDragData->aXP[nPnt1];
     692                 :          0 :                 long ndx0=aPnt.X()-aPnt1.X();
     693                 :          0 :                 long ndy0=aPnt.Y()-aPnt1.Y();
     694                 :          0 :                 bool bHLin=ndy0==0;
     695                 :          0 :                 bool bVLin=ndx0==0;
     696 [ #  # ][ #  # ]:          0 :                 if (!bHLin || !bVLin) {
     697                 :          0 :                     long ndx=aPos.X()-aPnt1.X();
     698                 :          0 :                     long ndy=aPos.Y()-aPnt1.Y();
     699                 :          0 :                     bPnt1=sal_True;
     700         [ #  # ]:          0 :                     double nXFact=0; if (!bVLin) nXFact=(double)ndx/(double)ndx0;
     701         [ #  # ]:          0 :                     double nYFact=0; if (!bHLin) nYFact=(double)ndy/(double)ndy0;
     702 [ #  # ][ #  # ]:          0 :                     bool bHor=bHLin || (!bVLin && (nXFact>nYFact) ==bBigOrtho);
                 [ #  # ]
     703 [ #  # ][ #  # ]:          0 :                     bool bVer=bVLin || (!bHLin && (nXFact<=nYFact)==bBigOrtho);
                 [ #  # ]
     704         [ #  # ]:          0 :                     if (bHor) ndy=long(ndy0*nXFact);
     705         [ #  # ]:          0 :                     if (bVer) ndx=long(ndx0*nYFact);
     706                 :          0 :                     aNeuPos1=aPnt1;
     707                 :          0 :                     aNeuPos1.X()+=ndx;
     708                 :          0 :                     aNeuPos1.Y()+=ndy;
     709                 :            :                 }
     710                 :            :             }
     711 [ #  # ][ #  # ]:          0 :             if (nPnt2!=0xFFFF && !bNextIsControl) {
     712         [ #  # ]:          0 :                 Point aPnt2=mpSdrPathDragData->aXP[nPnt2];
     713                 :          0 :                 long ndx0=aPnt.X()-aPnt2.X();
     714                 :          0 :                 long ndy0=aPnt.Y()-aPnt2.Y();
     715                 :          0 :                 bool bHLin=ndy0==0;
     716                 :          0 :                 bool bVLin=ndx0==0;
     717 [ #  # ][ #  # ]:          0 :                 if (!bHLin || !bVLin) {
     718                 :          0 :                     long ndx=aPos.X()-aPnt2.X();
     719                 :          0 :                     long ndy=aPos.Y()-aPnt2.Y();
     720                 :          0 :                     bPnt2=sal_True;
     721         [ #  # ]:          0 :                     double nXFact=0; if (!bVLin) nXFact=(double)ndx/(double)ndx0;
     722         [ #  # ]:          0 :                     double nYFact=0; if (!bHLin) nYFact=(double)ndy/(double)ndy0;
     723 [ #  # ][ #  # ]:          0 :                     bool bHor=bHLin || (!bVLin && (nXFact>nYFact) ==bBigOrtho);
                 [ #  # ]
     724 [ #  # ][ #  # ]:          0 :                     bool bVer=bVLin || (!bHLin && (nXFact<=nYFact)==bBigOrtho);
                 [ #  # ]
     725         [ #  # ]:          0 :                     if (bHor) ndy=long(ndy0*nXFact);
     726         [ #  # ]:          0 :                     if (bVer) ndx=long(ndx0*nYFact);
     727                 :          0 :                     aNeuPos2=aPnt2;
     728                 :          0 :                     aNeuPos2.X()+=ndx;
     729                 :          0 :                     aNeuPos2.Y()+=ndy;
     730                 :            :                 }
     731                 :            :             }
     732 [ #  # ][ #  # ]:          0 :             if (bPnt1 && bPnt2) { // both alternatives exist (and compete)
     733 [ #  # ][ #  # ]:          0 :                 BigInt nX1(aNeuPos1.X()-aPos.X()); nX1*=nX1;
     734 [ #  # ][ #  # ]:          0 :                 BigInt nY1(aNeuPos1.Y()-aPos.Y()); nY1*=nY1;
     735 [ #  # ][ #  # ]:          0 :                 BigInt nX2(aNeuPos2.X()-aPos.X()); nX2*=nX2;
     736 [ #  # ][ #  # ]:          0 :                 BigInt nY2(aNeuPos2.Y()-aPos.Y()); nY2*=nY2;
     737         [ #  # ]:          0 :                 nX1+=nY1; // correction distance to square
     738         [ #  # ]:          0 :                 nX2+=nY2; // correction distance to square
     739                 :            :                 // let the alternative that allows fewer correction win
     740 [ #  # ][ #  # ]:          0 :                 if (nX1<nX2) bPnt2=sal_False; else bPnt1=sal_False;
     741                 :            :             }
     742 [ #  # ][ #  # ]:          0 :             if (bPnt1) rDrag.Now()=aNeuPos1;
     743 [ #  # ][ #  # ]:          0 :             if (bPnt2) rDrag.Now()=aNeuPos2;
     744                 :            :         }
     745 [ #  # ][ #  # ]:          0 :         rDrag.SetActionRect(Rectangle(rDrag.GetNow(),rDrag.GetNow()));
                 [ #  # ]
     746                 :            : 
     747                 :            :         // specially for IBM: Eliminate points if both adjoining lines form near 180 degrees angle anyway
     748 [ #  # ][ #  # ]:          0 :         if (!bControl && rDrag.GetView()!=NULL && rDrag.GetView()->IsEliminatePolyPoints() &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     749                 :          0 :             !bBegPnt && !bEndPnt && !bPrevIsControl && !bNextIsControl)
     750                 :            :         {
     751         [ #  # ]:          0 :             Point aPt(mpSdrPathDragData->aXP[nNextPnt]);
     752         [ #  # ]:          0 :             aPt-=rDrag.GetNow();
     753         [ #  # ]:          0 :             long nWink1=GetAngle(aPt);
     754         [ #  # ]:          0 :             aPt=rDrag.GetNow();
     755         [ #  # ]:          0 :             aPt-=mpSdrPathDragData->aXP[nPrevPnt];
     756         [ #  # ]:          0 :             long nWink2=GetAngle(aPt);
     757                 :          0 :             long nDiff=nWink1-nWink2;
     758                 :          0 :             nDiff=Abs(nDiff);
     759                 :          0 :             mpSdrPathDragData->bEliminate=nDiff<=rDrag.GetView()->GetEliminatePolyPointLimitAngle();
     760         [ #  # ]:          0 :             if (mpSdrPathDragData->bEliminate) { // adapt position, Smooth is true for the ends
     761         [ #  # ]:          0 :                 aPt=mpSdrPathDragData->aXP[nNextPnt];
     762         [ #  # ]:          0 :                 aPt+=mpSdrPathDragData->aXP[nPrevPnt];
     763                 :          0 :                 aPt/=2;
     764         [ #  # ]:          0 :                 rDrag.Now()=aPt;
     765                 :            :             }
     766                 :            :         }
     767                 :            : 
     768                 :            :         // we dragged by this distance
     769 [ #  # ][ #  # ]:          0 :         Point aDiff(rDrag.GetNow()); aDiff-=mpSdrPathDragData->aXP[nPnt];
     770                 :            : 
     771                 :            :         /* There are 8 possible cases:
     772                 :            :               X      1. A control point neither on the left nor on the right.
     773                 :            :            o--X--o   2. There are control points on the left and the right, we are dragging a support point.
     774                 :            :            o--X      3. There is a control point on the left, we are dragging a support point.
     775                 :            :               X--o   4. There is a control point on the right, we are dragging a support point.
     776                 :            :            x--O--o   5. There are control points on the left and the right, we are dragging the left one.
     777                 :            :            x--O      6. There is a control point on the left, we are dragging it.
     778                 :            :            o--O--x   7. There are control points on the left and the right, we are dragging the right one.
     779                 :            :               O--x   8. There is a control point on the right, we are dragging it.
     780                 :            :            Note: modifying a line (not a curve!) might create a curve on the other end of the line
     781                 :            :            if Smooth is set there (with control points aligned to line).
     782                 :            :         */
     783                 :            : 
     784         [ #  # ]:          0 :         mpSdrPathDragData->aXP[nPnt]+=aDiff;
     785                 :            : 
     786                 :            :         // now check symmetric plus handles
     787         [ #  # ]:          0 :         if (bControl) { // cases 5,6,7,8
     788                 :          0 :             sal_uInt16   nSt=nPnt;   // the associated support point
     789                 :          0 :             sal_uInt16   nFix=nPnt;  // the opposing control point
     790         [ #  # ]:          0 :             if (bIsNextControl) { // if the next one is a control point, the on before has to be a support point
     791                 :          0 :                 nSt=nPrevPnt;
     792                 :          0 :                 nFix=nPrevPrevPnt;
     793                 :            :             } else {
     794                 :          0 :                 nSt=nNextPnt;
     795                 :          0 :                 nFix=nNextNextPnt;
     796                 :            :             }
     797 [ #  # ][ #  # ]:          0 :             if (mpSdrPathDragData->aXP.IsSmooth(nSt)) {
     798         [ #  # ]:          0 :                 mpSdrPathDragData->aXP.CalcSmoothJoin(nSt,nPnt,nFix);
     799                 :            :             }
     800                 :            :         }
     801                 :            : 
     802         [ #  # ]:          0 :         if (!bControl) { // Cases 1,2,3,4. In case 1, nothing happens; in cases 3 and 4, there is more following below.
     803                 :            :             // move both control points
     804 [ #  # ][ #  # ]:          0 :             if (bPrevIsControl) mpSdrPathDragData->aXP[nPrevPnt]+=aDiff;
     805 [ #  # ][ #  # ]:          0 :             if (bNextIsControl) mpSdrPathDragData->aXP[nNextPnt]+=aDiff;
     806                 :            :             // align control point to line, if appropriate
     807 [ #  # ][ #  # ]:          0 :             if (mpSdrPathDragData->aXP.IsSmooth(nPnt)) {
     808 [ #  # ][ #  # ]:          0 :                 if (bPrevIsControl && !bNextIsControl && !bEndPnt) { // case 3
                 [ #  # ]
     809         [ #  # ]:          0 :                     mpSdrPathDragData->aXP.CalcSmoothJoin(nPnt,nNextPnt,nPrevPnt);
     810                 :            :                 }
     811 [ #  # ][ #  # ]:          0 :                 if (bNextIsControl && !bPrevIsControl && !bBegPnt) { // case 4
                 [ #  # ]
     812         [ #  # ]:          0 :                     mpSdrPathDragData->aXP.CalcSmoothJoin(nPnt,nPrevPnt,nNextPnt);
     813                 :            :                 }
     814                 :            :             }
     815                 :            :             // Now check the other ends of the line (nPnt+-1). If there is a
     816                 :            :             // curve (IsControl(nPnt+-2)) with SmoothJoin (nPnt+-1), the
     817                 :            :             // associated control point (nPnt+-2) has to be adapted.
     818 [ #  # ][ #  # ]:          0 :             if (!bBegPnt && !bPrevIsControl && !bPrevIsBegPnt && mpSdrPathDragData->aXP.IsSmooth(nPrevPnt)) {
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     819 [ #  # ][ #  # ]:          0 :                 if (mpSdrPathDragData->aXP.IsControl(nPrevPrevPnt)) {
     820         [ #  # ]:          0 :                     mpSdrPathDragData->aXP.CalcSmoothJoin(nPrevPnt,nPnt,nPrevPrevPnt);
     821                 :            :                 }
     822                 :            :             }
     823 [ #  # ][ #  # ]:          0 :             if (!bEndPnt && !bNextIsControl && !bNextIsEndPnt && mpSdrPathDragData->aXP.IsSmooth(nNextPnt)) {
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     824 [ #  # ][ #  # ]:          0 :                 if (mpSdrPathDragData->aXP.IsControl(nNextNextPnt)) {
     825         [ #  # ]:          0 :                     mpSdrPathDragData->aXP.CalcSmoothJoin(nNextPnt,nPnt,nNextNextPnt);
     826                 :            :                 }
     827                 :            :             }
     828                 :            :         }
     829                 :            :     }
     830                 :            : 
     831                 :          0 :     return true;
     832                 :            : }
     833                 :            : 
     834                 :          0 : bool ImpPathForDragAndCreate::endPathDrag(SdrDragStat& rDrag)
     835                 :            : {
     836                 :          0 :     Point aLinePt1;
     837                 :          0 :     Point aLinePt2;
     838                 :          0 :     bool bLineGlueMirror(OBJ_LINE == meObjectKind);
     839         [ #  # ]:          0 :     if (bLineGlueMirror) {
     840         [ #  # ]:          0 :         XPolygon& rXP=aPathPolygon[0];
     841         [ #  # ]:          0 :         aLinePt1=rXP[0];
     842         [ #  # ]:          0 :         aLinePt2=rXP[1];
     843                 :            :     }
     844                 :            : 
     845 [ #  # ][ #  # ]:          0 :     if(!mpSdrPathDragData || !mpSdrPathDragData->bValid)
     846                 :            :     {
     847                 :            :         OSL_FAIL("ImpPathForDragAndCreate::MovDrag(): ImpSdrPathDragData is invalid.");
     848                 :          0 :         return false;
     849                 :            :     }
     850                 :            : 
     851         [ #  # ]:          0 :     if(mpSdrPathDragData->IsMultiPointDrag())
     852                 :            :     {
     853         [ #  # ]:          0 :         aPathPolygon = mpSdrPathDragData->maMove;
     854                 :            :     }
     855                 :            :     else
     856                 :            :     {
     857                 :          0 :         const SdrHdl* pHdl=rDrag.GetHdl();
     858                 :            : 
     859                 :            :         // reference the polygon
     860         [ #  # ]:          0 :         XPolygon& rXP=aPathPolygon[(sal_uInt16)pHdl->GetPolyNum()];
     861                 :            : 
     862                 :            :         // the 5 points that might have changed
     863 [ #  # ][ #  # ]:          0 :         if (!mpSdrPathDragData->bPrevIsBegPnt) rXP[mpSdrPathDragData->nPrevPrevPnt0]=mpSdrPathDragData->aXP[mpSdrPathDragData->nPrevPrevPnt];
                 [ #  # ]
     864 [ #  # ][ #  # ]:          0 :         if (!mpSdrPathDragData->bNextIsEndPnt) rXP[mpSdrPathDragData->nNextNextPnt0]=mpSdrPathDragData->aXP[mpSdrPathDragData->nNextNextPnt];
                 [ #  # ]
     865 [ #  # ][ #  # ]:          0 :         if (!mpSdrPathDragData->bBegPnt)       rXP[mpSdrPathDragData->nPrevPnt0]    =mpSdrPathDragData->aXP[mpSdrPathDragData->nPrevPnt];
                 [ #  # ]
     866 [ #  # ][ #  # ]:          0 :         if (!mpSdrPathDragData->bEndPnt)       rXP[mpSdrPathDragData->nNextPnt0]    =mpSdrPathDragData->aXP[mpSdrPathDragData->nNextPnt];
                 [ #  # ]
     867 [ #  # ][ #  # ]:          0 :         rXP[mpSdrPathDragData->nPnt0]        =mpSdrPathDragData->aXP[mpSdrPathDragData->nPnt];
     868                 :            : 
     869                 :            :         // for closed objects: last point has to be equal to first point
     870 [ #  # ][ #  # ]:          0 :         if (mpSdrPathDragData->bClosed) rXP[rXP.GetPointCount()-1]=rXP[0];
         [ #  # ][ #  # ]
     871                 :            : 
     872         [ #  # ]:          0 :         if (mpSdrPathDragData->bEliminate)
     873                 :            :         {
     874         [ #  # ]:          0 :             basegfx::B2DPolyPolygon aTempPolyPolygon(aPathPolygon.getB2DPolyPolygon());
     875                 :            :             sal_uInt32 nPoly,nPnt;
     876                 :            : 
     877 [ #  # ][ #  # ]:          0 :             if(PolyPolygonEditor::GetRelativePolyPoint(aTempPolyPolygon, rDrag.GetHdl()->GetSourceHdlNum(), nPoly, nPnt))
     878                 :            :             {
     879         [ #  # ]:          0 :                 basegfx::B2DPolygon aCandidate(aTempPolyPolygon.getB2DPolygon(nPoly));
     880         [ #  # ]:          0 :                 aCandidate.remove(nPnt);
     881                 :            : 
     882 [ #  # ][ #  # ]:          0 :                 if((IsClosed(meObjectKind) && aCandidate.count() < 3L) || aCandidate.count() < 2L)
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     883                 :            :                 {
     884         [ #  # ]:          0 :                     aTempPolyPolygon.remove(nPoly);
     885                 :            :                 }
     886                 :            :                 else
     887                 :            :                 {
     888         [ #  # ]:          0 :                     aTempPolyPolygon.setB2DPolygon(nPoly, aCandidate);
     889         [ #  # ]:          0 :                 }
     890                 :            :             }
     891                 :            : 
     892 [ #  # ][ #  # ]:          0 :             aPathPolygon = XPolyPolygon(aTempPolyPolygon);
         [ #  # ][ #  # ]
     893                 :            :         }
     894                 :            : 
     895                 :            :         // adapt angle for text beneath a simple line
     896         [ #  # ]:          0 :         if (bLineGlueMirror)
     897                 :            :         {
     898 [ #  # ][ #  # ]:          0 :             Point aLinePt1_(aPathPolygon[0][0]);
     899 [ #  # ][ #  # ]:          0 :             Point aLinePt2_(aPathPolygon[0][1]);
     900                 :          0 :             bool bXMirr=(aLinePt1_.X()>aLinePt2_.X())!=(aLinePt1.X()>aLinePt2.X());
     901                 :          0 :             bool bYMirr=(aLinePt1_.Y()>aLinePt2_.Y())!=(aLinePt1.Y()>aLinePt2.Y());
     902 [ #  # ][ #  # ]:          0 :             if (bXMirr || bYMirr) {
     903 [ #  # ][ #  # ]:          0 :                 Point aRef1(mrSdrPathObject.GetSnapRect().Center());
     904         [ #  # ]:          0 :                 if (bXMirr) {
     905                 :          0 :                     Point aRef2(aRef1);
     906                 :          0 :                     aRef2.Y()++;
     907         [ #  # ]:          0 :                     mrSdrPathObject.NbcMirrorGluePoints(aRef1,aRef2);
     908                 :            :                 }
     909         [ #  # ]:          0 :                 if (bYMirr) {
     910                 :          0 :                     Point aRef2(aRef1);
     911                 :          0 :                     aRef2.X()++;
     912         [ #  # ]:          0 :                     mrSdrPathObject.NbcMirrorGluePoints(aRef1,aRef2);
     913                 :            :                 }
     914                 :            :             }
     915                 :            :         }
     916                 :            :     }
     917                 :            : 
     918 [ #  # ][ #  # ]:          0 :     delete mpSdrPathDragData;
     919                 :          0 :     mpSdrPathDragData = 0;
     920                 :            : 
     921                 :          0 :     return true;
     922                 :            : }
     923                 :            : 
     924                 :            : 
     925                 :          0 : String ImpPathForDragAndCreate::getSpecialDragComment(const SdrDragStat& rDrag) const
     926                 :            : {
     927         [ #  # ]:          0 :     XubString aStr;
     928                 :          0 :     const SdrHdl* pHdl = rDrag.GetHdl();
     929 [ #  # ][ #  # ]:          0 :     const bool bCreateComment(rDrag.GetView() && &mrSdrPathObject == rDrag.GetView()->GetCreateObj());
     930                 :            : 
     931 [ #  # ][ #  # ]:          0 :     if(bCreateComment && rDrag.GetUser())
                 [ #  # ]
     932                 :            :     {
     933                 :            :         // #i103058# re-add old creation comment mode
     934                 :          0 :         ImpPathCreateUser* pU = (ImpPathCreateUser*)rDrag.GetUser();
     935                 :          0 :         const SdrObjKind eKindMerk(meObjectKind);
     936                 :          0 :         mrSdrPathObject.meKind = pU->eAktKind;
     937                 :          0 :         rtl::OUString aTmp;
     938         [ #  # ]:          0 :         mrSdrPathObject.ImpTakeDescriptionStr(STR_ViewCreateObj, aTmp);
     939         [ #  # ]:          0 :         aStr = aTmp;
     940                 :          0 :         mrSdrPathObject.meKind = eKindMerk;
     941                 :            : 
     942         [ #  # ]:          0 :         Point aPrev(rDrag.GetPrev());
     943         [ #  # ]:          0 :         Point aNow(rDrag.GetNow());
     944                 :            : 
     945         [ #  # ]:          0 :         if(pU->bLine)
     946                 :          0 :             aNow = pU->aLineEnd;
     947                 :            : 
     948                 :          0 :         aNow -= aPrev;
     949         [ #  # ]:          0 :         aStr.AppendAscii(" (");
     950                 :            : 
     951                 :          0 :         rtl::OUString aMetr;
     952                 :            : 
     953         [ #  # ]:          0 :         if(pU->bCircle)
     954                 :            :         {
     955 [ #  # ][ #  # ]:          0 :             mrSdrPathObject.GetModel()->TakeWinkStr(Abs(pU->nCircRelWink), aMetr);
     956 [ #  # ][ #  # ]:          0 :             aStr.Append(aMetr);
                 [ #  # ]
     957         [ #  # ]:          0 :             aStr.AppendAscii(" r=");
     958 [ #  # ][ #  # ]:          0 :             mrSdrPathObject.GetModel()->TakeMetricStr(pU->nCircRadius, aMetr, sal_True);
     959 [ #  # ][ #  # ]:          0 :             aStr.Append(aMetr);
                 [ #  # ]
     960                 :            :         }
     961                 :            : 
     962         [ #  # ]:          0 :         aStr.AppendAscii("dx=");
     963 [ #  # ][ #  # ]:          0 :         mrSdrPathObject.GetModel()->TakeMetricStr(aNow.X(), aMetr, sal_True);
     964 [ #  # ][ #  # ]:          0 :         aStr.Append(aMetr);
                 [ #  # ]
     965                 :            : 
     966         [ #  # ]:          0 :         aStr.AppendAscii(" dy=");
     967 [ #  # ][ #  # ]:          0 :         mrSdrPathObject.GetModel()->TakeMetricStr(aNow.Y(), aMetr, sal_True);
     968 [ #  # ][ #  # ]:          0 :         aStr.Append(aMetr);
                 [ #  # ]
     969                 :            : 
     970         [ #  # ]:          0 :         if(!IsFreeHand(meObjectKind))
     971                 :            :         {
     972         [ #  # ]:          0 :             sal_Int32 nLen(GetLen(aNow));
     973         [ #  # ]:          0 :             aStr.AppendAscii("  l=");
     974 [ #  # ][ #  # ]:          0 :             mrSdrPathObject.GetModel()->TakeMetricStr(nLen, aMetr, sal_True);
     975 [ #  # ][ #  # ]:          0 :             aStr.Append(aMetr);
                 [ #  # ]
     976                 :            : 
     977         [ #  # ]:          0 :             sal_Int32 nWink(GetAngle(aNow));
     978         [ #  # ]:          0 :             aStr += sal_Unicode(' ');
     979 [ #  # ][ #  # ]:          0 :             mrSdrPathObject.GetModel()->TakeWinkStr(nWink, aMetr);
     980 [ #  # ][ #  # ]:          0 :             aStr.Append(aMetr);
                 [ #  # ]
     981                 :            :         }
     982                 :            : 
     983         [ #  # ]:          0 :         aStr += sal_Unicode(')');
     984                 :            :     }
     985 [ #  # ][ #  # ]:          0 :     else if(!mrSdrPathObject.GetModel() || !pHdl)
         [ #  # ][ #  # ]
     986                 :            :     {
     987                 :            :         // #i103058# fallback when no model and/or Handle, both needed
     988                 :            :         // for else-path
     989                 :          0 :         rtl::OUString aTmp;
     990         [ #  # ]:          0 :         mrSdrPathObject.ImpTakeDescriptionStr(STR_DragPathObj, aTmp);
     991         [ #  # ]:          0 :         aStr = aTmp;
     992                 :            :     }
     993                 :            :     else
     994                 :            :     {
     995                 :            :         // #i103058# standard for modification; model and handle needed
     996                 :          0 :         ImpSdrPathDragData* pDragData = mpSdrPathDragData;
     997                 :            : 
     998         [ #  # ]:          0 :         if(!pDragData)
     999                 :            :         {
    1000                 :            :             // getSpecialDragComment is also used from create, so fallback to GetUser()
    1001                 :            :             // when mpSdrPathDragData is not set
    1002                 :          0 :             pDragData = (ImpSdrPathDragData*)rDrag.GetUser();
    1003                 :            :         }
    1004                 :            : 
    1005         [ #  # ]:          0 :         if(!pDragData)
    1006                 :            :         {
    1007                 :            :             OSL_FAIL("ImpPathForDragAndCreate::MovDrag(): ImpSdrPathDragData is invalid.");
    1008         [ #  # ]:          0 :             return String();
    1009                 :            :         }
    1010                 :            : 
    1011 [ #  # ][ #  # ]:          0 :         if(!pDragData->IsMultiPointDrag() && pDragData->bEliminate)
                 [ #  # ]
    1012                 :            :         {
    1013                 :            :             // point of ...
    1014                 :          0 :             rtl::OUString aTmp;
    1015         [ #  # ]:          0 :             mrSdrPathObject.ImpTakeDescriptionStr(STR_ViewMarkedPoint, aTmp);
    1016         [ #  # ]:          0 :             aStr = aTmp;
    1017                 :            : 
    1018                 :            :             // delete %O
    1019         [ #  # ]:          0 :             XubString aStr2(ImpGetResStr(STR_EditDelete));
    1020                 :            : 
    1021                 :            :             // UNICODE: delete point of ...
    1022         [ #  # ]:          0 :             aStr2.SearchAndReplaceAscii("%1", aStr);
    1023                 :            : 
    1024 [ #  # ][ #  # ]:          0 :             return aStr2;
    1025                 :            :         }
    1026                 :            : 
    1027                 :            :         // dx=0.00 dy=0.00                -- both sides bezier
    1028                 :            :         // dx=0.00 dy=0.00  l=0.00 0.00°  -- one bezier/lever on one side, a start, or an ending
    1029                 :            :         // dx=0.00 dy=0.00  l=0.00 0.00° / l=0.00 0.00° -- in between
    1030                 :          0 :         rtl::OUString aMetr;
    1031         [ #  # ]:          0 :         Point aBeg(rDrag.GetStart());
    1032         [ #  # ]:          0 :         Point aNow(rDrag.GetNow());
    1033                 :            : 
    1034 [ #  # ][ #  # ]:          0 :         aStr = String();
                 [ #  # ]
    1035         [ #  # ]:          0 :         aStr.AppendAscii("dx=");
    1036 [ #  # ][ #  # ]:          0 :         mrSdrPathObject.GetModel()->TakeMetricStr(aNow.X() - aBeg.X(), aMetr, sal_True);
    1037 [ #  # ][ #  # ]:          0 :         aStr.Append(aMetr);
                 [ #  # ]
    1038                 :            : 
    1039         [ #  # ]:          0 :         aStr.AppendAscii(" dy=");
    1040 [ #  # ][ #  # ]:          0 :         mrSdrPathObject.GetModel()->TakeMetricStr(aNow.Y() - aBeg.Y(), aMetr, sal_True);
    1041 [ #  # ][ #  # ]:          0 :         aStr.Append(aMetr);
                 [ #  # ]
    1042                 :            : 
    1043         [ #  # ]:          0 :         if(!pDragData->IsMultiPointDrag())
    1044                 :            :         {
    1045                 :          0 :             sal_uInt16 nPntNum((sal_uInt16)pHdl->GetPointNum());
    1046         [ #  # ]:          0 :             const XPolygon& rXPoly = aPathPolygon[(sal_uInt16)rDrag.GetHdl()->GetPolyNum()];
    1047         [ #  # ]:          0 :             sal_uInt16 nPntAnz((sal_uInt16)rXPoly.GetPointCount());
    1048                 :          0 :             sal_Bool bClose(IsClosed(meObjectKind));
    1049                 :            : 
    1050         [ #  # ]:          0 :             if(bClose)
    1051                 :          0 :                 nPntAnz--;
    1052                 :            : 
    1053         [ #  # ]:          0 :             if(pHdl->IsPlusHdl())
    1054                 :            :             {
    1055                 :            :                 // lever
    1056                 :          0 :                 sal_uInt16 nRef(nPntNum);
    1057                 :            : 
    1058 [ #  # ][ #  # ]:          0 :                 if(rXPoly.IsControl(nPntNum + 1))
    1059                 :          0 :                     nRef--;
    1060                 :            :                 else
    1061                 :          0 :                     nRef++;
    1062                 :            : 
    1063         [ #  # ]:          0 :                 aNow -= rXPoly[nRef];
    1064                 :            : 
    1065         [ #  # ]:          0 :                 sal_Int32 nLen(GetLen(aNow));
    1066         [ #  # ]:          0 :                 aStr.AppendAscii("  l=");
    1067 [ #  # ][ #  # ]:          0 :                 mrSdrPathObject.GetModel()->TakeMetricStr(nLen, aMetr, sal_True);
    1068 [ #  # ][ #  # ]:          0 :                 aStr.Append(aMetr);
                 [ #  # ]
    1069                 :            : 
    1070         [ #  # ]:          0 :                 sal_Int32 nWink(GetAngle(aNow));
    1071         [ #  # ]:          0 :                 aStr += sal_Unicode(' ');
    1072 [ #  # ][ #  # ]:          0 :                 mrSdrPathObject.GetModel()->TakeWinkStr(nWink, aMetr);
    1073 [ #  # ][ #  # ]:          0 :                 aStr.Append(aMetr);
                 [ #  # ]
    1074                 :            :             }
    1075         [ #  # ]:          0 :             else if(nPntAnz > 1)
    1076                 :            :             {
    1077                 :          0 :                 sal_uInt16 nPntMax(nPntAnz - 1);
    1078                 :          0 :                 Point aPt1,aPt2;
    1079                 :          0 :                 sal_Bool bIsClosed(IsClosed(meObjectKind));
    1080                 :          0 :                 sal_Bool bPt1(nPntNum > 0);
    1081                 :          0 :                 sal_Bool bPt2(nPntNum < nPntMax);
    1082                 :            : 
    1083 [ #  # ][ #  # ]:          0 :                 if(bIsClosed && nPntAnz > 2)
    1084                 :            :                 {
    1085                 :          0 :                     bPt1 = sal_True;
    1086                 :          0 :                     bPt2 = sal_True;
    1087                 :            :                 }
    1088                 :            : 
    1089                 :            :                 sal_uInt16 nPt1,nPt2;
    1090                 :            : 
    1091         [ #  # ]:          0 :                 if(nPntNum > 0)
    1092                 :          0 :                     nPt1 = nPntNum - 1;
    1093                 :            :                 else
    1094                 :          0 :                     nPt1 = nPntMax;
    1095                 :            : 
    1096         [ #  # ]:          0 :                 if(nPntNum < nPntMax)
    1097                 :          0 :                     nPt2 = nPntNum + 1;
    1098                 :            :                 else
    1099                 :          0 :                     nPt2 = 0;
    1100                 :            : 
    1101 [ #  # ][ #  # ]:          0 :                 if(bPt1 && rXPoly.IsControl(nPt1))
         [ #  # ][ #  # ]
    1102                 :          0 :                     bPt1 = sal_False; // don't display
    1103                 :            : 
    1104 [ #  # ][ #  # ]:          0 :                 if(bPt2 && rXPoly.IsControl(nPt2))
         [ #  # ][ #  # ]
    1105                 :          0 :                     bPt2 = sal_False; // of bezier data
    1106                 :            : 
    1107         [ #  # ]:          0 :                 if(bPt1)
    1108                 :            :                 {
    1109                 :          0 :                     Point aPt(aNow);
    1110         [ #  # ]:          0 :                     aPt -= rXPoly[nPt1];
    1111                 :            : 
    1112         [ #  # ]:          0 :                     sal_Int32 nLen(GetLen(aPt));
    1113         [ #  # ]:          0 :                     aStr.AppendAscii("  l=");
    1114 [ #  # ][ #  # ]:          0 :                     mrSdrPathObject.GetModel()->TakeMetricStr(nLen, aMetr, sal_True);
    1115         [ #  # ]:          0 :                     aStr += aMetr;
    1116                 :            : 
    1117         [ #  # ]:          0 :                     sal_Int32 nWink(GetAngle(aPt));
    1118         [ #  # ]:          0 :                     aStr += sal_Unicode(' ');
    1119 [ #  # ][ #  # ]:          0 :                     mrSdrPathObject.GetModel()->TakeWinkStr(nWink, aMetr);
    1120         [ #  # ]:          0 :                     aStr += aMetr;
    1121                 :            :                 }
    1122                 :            : 
    1123         [ #  # ]:          0 :                 if(bPt2)
    1124                 :            :                 {
    1125         [ #  # ]:          0 :                     if(bPt1)
    1126         [ #  # ]:          0 :                         aStr.AppendAscii(" / ");
    1127                 :            :                     else
    1128         [ #  # ]:          0 :                         aStr.AppendAscii("  ");
    1129                 :            : 
    1130                 :          0 :                     Point aPt(aNow);
    1131         [ #  # ]:          0 :                     aPt -= rXPoly[nPt2];
    1132                 :            : 
    1133         [ #  # ]:          0 :                     sal_Int32 nLen(GetLen(aPt));
    1134         [ #  # ]:          0 :                     aStr.AppendAscii("l=");
    1135 [ #  # ][ #  # ]:          0 :                     mrSdrPathObject.GetModel()->TakeMetricStr(nLen, aMetr, sal_True);
    1136         [ #  # ]:          0 :                     aStr += aMetr;
    1137                 :            : 
    1138         [ #  # ]:          0 :                     sal_Int32 nWink(GetAngle(aPt));
    1139         [ #  # ]:          0 :                     aStr += sal_Unicode(' ');
    1140 [ #  # ][ #  # ]:          0 :                     mrSdrPathObject.GetModel()->TakeWinkStr(nWink, aMetr);
    1141         [ #  # ]:          0 :                     aStr += aMetr;
    1142                 :            :                 }
    1143                 :            :             }
    1144                 :          0 :         }
    1145                 :            :     }
    1146                 :            : 
    1147 [ #  # ][ #  # ]:          0 :     return aStr;
    1148                 :            : }
    1149                 :            : 
    1150                 :          0 : basegfx::B2DPolyPolygon ImpPathForDragAndCreate::getSpecialDragPoly(const SdrDragStat& rDrag) const
    1151                 :            : {
    1152 [ #  # ][ #  # ]:          0 :     if(!mpSdrPathDragData || !mpSdrPathDragData->bValid)
    1153                 :            :     {
    1154                 :            :         OSL_FAIL("ImpPathForDragAndCreate::MovDrag(): ImpSdrPathDragData is invalid.");
    1155         [ #  # ]:          0 :         return basegfx::B2DPolyPolygon();
    1156                 :            :     }
    1157                 :            : 
    1158         [ #  # ]:          0 :     XPolyPolygon aRetval;
    1159                 :            : 
    1160         [ #  # ]:          0 :     if(mpSdrPathDragData->IsMultiPointDrag())
    1161                 :            :     {
    1162         [ #  # ]:          0 :         aRetval.Insert(mpSdrPathDragData->maMove);
    1163                 :            :     }
    1164                 :            :     else
    1165                 :            :     {
    1166         [ #  # ]:          0 :         const XPolygon& rXP=aPathPolygon[(sal_uInt16)rDrag.GetHdl()->GetPolyNum()];
    1167 [ #  # ][ #  # ]:          0 :         if (rXP.GetPointCount()<=2) {
    1168         [ #  # ]:          0 :             XPolygon aXPoly(rXP);
    1169 [ #  # ][ #  # ]:          0 :             aXPoly[(sal_uInt16)rDrag.GetHdl()->GetPointNum()]=rDrag.GetNow();
    1170         [ #  # ]:          0 :             aRetval.Insert(aXPoly);
    1171 [ #  # ][ #  # ]:          0 :             return aRetval.getB2DPolyPolygon();
    1172                 :            :         }
    1173                 :            :         // copy certain data locally to use less code and have faster access times
    1174                 :          0 :         bool bClosed           =mpSdrPathDragData->bClosed       ; // closed object?
    1175                 :          0 :         sal_uInt16   nPntAnz       =mpSdrPathDragData->nPntAnz       ; // number of points
    1176                 :          0 :         sal_uInt16   nPnt          =mpSdrPathDragData->nPnt          ; // number of points in the polygon
    1177                 :          0 :         bool bBegPnt           =mpSdrPathDragData->bBegPnt       ; // dragged point is the first point of a Polyline
    1178                 :          0 :         bool bEndPnt           =mpSdrPathDragData->bEndPnt       ; // dragged point is the last point of a Polyline
    1179                 :          0 :         sal_uInt16   nPrevPnt      =mpSdrPathDragData->nPrevPnt      ; // index of the previous point
    1180                 :          0 :         sal_uInt16   nNextPnt      =mpSdrPathDragData->nNextPnt      ; // index of the next point
    1181                 :          0 :         bool bPrevIsBegPnt     =mpSdrPathDragData->bPrevIsBegPnt ; // previous point is first point of a Polyline
    1182                 :          0 :         bool bNextIsEndPnt     =mpSdrPathDragData->bNextIsEndPnt ; // next point is last point of a Polyline
    1183                 :          0 :         sal_uInt16   nPrevPrevPnt  =mpSdrPathDragData->nPrevPrevPnt  ; // index of the point before the previous point
    1184                 :          0 :         sal_uInt16   nNextNextPnt  =mpSdrPathDragData->nNextNextPnt  ; // index of the point after the last point
    1185                 :          0 :         bool bControl          =mpSdrPathDragData->bControl      ; // point is a control point
    1186                 :          0 :         bool bIsNextControl    =mpSdrPathDragData->bIsNextControl; //point is a control point after a support point
    1187                 :          0 :         bool bPrevIsControl    =mpSdrPathDragData->bPrevIsControl; // if nPnt is a support point: there's a control point before
    1188                 :          0 :         bool bNextIsControl    =mpSdrPathDragData->bNextIsControl; // if nPnt is a support point: there's a control point after
    1189         [ #  # ]:          0 :         XPolygon aXPoly(mpSdrPathDragData->aXP);
    1190         [ #  # ]:          0 :         XPolygon aLine1(2);
    1191         [ #  # ]:          0 :         XPolygon aLine2(2);
    1192         [ #  # ]:          0 :         XPolygon aLine3(2);
    1193         [ #  # ]:          0 :         XPolygon aLine4(2);
    1194         [ #  # ]:          0 :         if (bControl) {
    1195 [ #  # ][ #  # ]:          0 :             aLine1[1]=mpSdrPathDragData->aXP[nPnt];
    1196         [ #  # ]:          0 :             if (bIsNextControl) { // is this a control point after the support point?
    1197 [ #  # ][ #  # ]:          0 :                 aLine1[0]=mpSdrPathDragData->aXP[nPrevPnt];
    1198 [ #  # ][ #  # ]:          0 :                 aLine2[0]=mpSdrPathDragData->aXP[nNextNextPnt];
    1199 [ #  # ][ #  # ]:          0 :                 aLine2[1]=mpSdrPathDragData->aXP[nNextPnt];
    1200 [ #  # ][ #  # ]:          0 :                 if (mpSdrPathDragData->aXP.IsSmooth(nPrevPnt) && !bPrevIsBegPnt && mpSdrPathDragData->aXP.IsControl(nPrevPrevPnt)) {
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1201 [ #  # ][ #  # ]:          0 :                     aXPoly.Insert(0,rXP[mpSdrPathDragData->nPrevPrevPnt0-1],XPOLY_CONTROL);
    1202 [ #  # ][ #  # ]:          0 :                     aXPoly.Insert(0,rXP[mpSdrPathDragData->nPrevPrevPnt0-2],XPOLY_NORMAL);
    1203                 :            :                     // leverage lines for the opposing curve segment
    1204 [ #  # ][ #  # ]:          0 :                     aLine3[0]=mpSdrPathDragData->aXP[nPrevPnt];
    1205 [ #  # ][ #  # ]:          0 :                     aLine3[1]=mpSdrPathDragData->aXP[nPrevPrevPnt];
    1206 [ #  # ][ #  # ]:          0 :                     aLine4[0]=rXP[mpSdrPathDragData->nPrevPrevPnt0-2];
    1207 [ #  # ][ #  # ]:          0 :                     aLine4[1]=rXP[mpSdrPathDragData->nPrevPrevPnt0-1];
    1208                 :            :                 } else {
    1209         [ #  # ]:          0 :                     aXPoly.Remove(0,1);
    1210                 :            :                 }
    1211                 :            :             } else { // else this is a control point before a support point
    1212 [ #  # ][ #  # ]:          0 :                 aLine1[0]=mpSdrPathDragData->aXP[nNextPnt];
    1213 [ #  # ][ #  # ]:          0 :                 aLine2[0]=mpSdrPathDragData->aXP[nPrevPrevPnt];
    1214 [ #  # ][ #  # ]:          0 :                 aLine2[1]=mpSdrPathDragData->aXP[nPrevPnt];
    1215 [ #  # ][ #  # ]:          0 :                 if (mpSdrPathDragData->aXP.IsSmooth(nNextPnt) && !bNextIsEndPnt && mpSdrPathDragData->aXP.IsControl(nNextNextPnt)) {
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1216 [ #  # ][ #  # ]:          0 :                     aXPoly.Insert(XPOLY_APPEND,rXP[mpSdrPathDragData->nNextNextPnt0+1],XPOLY_CONTROL);
    1217 [ #  # ][ #  # ]:          0 :                     aXPoly.Insert(XPOLY_APPEND,rXP[mpSdrPathDragData->nNextNextPnt0+2],XPOLY_NORMAL);
    1218                 :            :                     // leverage lines for the opposing curve segment
    1219 [ #  # ][ #  # ]:          0 :                     aLine3[0]=mpSdrPathDragData->aXP[nNextPnt];
    1220 [ #  # ][ #  # ]:          0 :                     aLine3[1]=mpSdrPathDragData->aXP[nNextNextPnt];
    1221 [ #  # ][ #  # ]:          0 :                     aLine4[0]=rXP[mpSdrPathDragData->nNextNextPnt0+2];
    1222 [ #  # ][ #  # ]:          0 :                     aLine4[1]=rXP[mpSdrPathDragData->nNextNextPnt0+1];
    1223                 :            :                 } else {
    1224 [ #  # ][ #  # ]:          0 :                     aXPoly.Remove(aXPoly.GetPointCount()-1,1);
    1225                 :            :                 }
    1226                 :            :             }
    1227                 :            :         } else { // else is not a control point
    1228         [ #  # ]:          0 :             if (mpSdrPathDragData->bEliminate) {
    1229         [ #  # ]:          0 :                 aXPoly.Remove(2,1);
    1230                 :            :             }
    1231 [ #  # ][ #  # ]:          0 :             if (bPrevIsControl) aXPoly.Insert(0,rXP[mpSdrPathDragData->nPrevPrevPnt0-1],XPOLY_NORMAL);
                 [ #  # ]
    1232 [ #  # ][ #  # ]:          0 :             else if (!bBegPnt && !bPrevIsBegPnt && mpSdrPathDragData->aXP.IsControl(nPrevPrevPnt)) {
         [ #  # ][ #  # ]
                 [ #  # ]
    1233 [ #  # ][ #  # ]:          0 :                 aXPoly.Insert(0,rXP[mpSdrPathDragData->nPrevPrevPnt0-1],XPOLY_CONTROL);
    1234 [ #  # ][ #  # ]:          0 :                 aXPoly.Insert(0,rXP[mpSdrPathDragData->nPrevPrevPnt0-2],XPOLY_NORMAL);
    1235                 :            :             } else {
    1236         [ #  # ]:          0 :                 aXPoly.Remove(0,1);
    1237 [ #  # ][ #  # ]:          0 :                 if (bBegPnt) aXPoly.Remove(0,1);
    1238                 :            :             }
    1239 [ #  # ][ #  # ]:          0 :             if (bNextIsControl) aXPoly.Insert(XPOLY_APPEND,rXP[mpSdrPathDragData->nNextNextPnt0+1],XPOLY_NORMAL);
                 [ #  # ]
    1240 [ #  # ][ #  # ]:          0 :             else if (!bEndPnt && !bNextIsEndPnt && mpSdrPathDragData->aXP.IsControl(nNextNextPnt)) {
         [ #  # ][ #  # ]
                 [ #  # ]
    1241 [ #  # ][ #  # ]:          0 :                 aXPoly.Insert(XPOLY_APPEND,rXP[mpSdrPathDragData->nNextNextPnt0+1],XPOLY_CONTROL);
    1242 [ #  # ][ #  # ]:          0 :                 aXPoly.Insert(XPOLY_APPEND,rXP[mpSdrPathDragData->nNextNextPnt0+2],XPOLY_NORMAL);
    1243                 :            :             } else {
    1244 [ #  # ][ #  # ]:          0 :                 aXPoly.Remove(aXPoly.GetPointCount()-1,1);
    1245 [ #  # ][ #  # ]:          0 :                 if (bEndPnt) aXPoly.Remove(aXPoly.GetPointCount()-1,1);
                 [ #  # ]
    1246                 :            :             }
    1247         [ #  # ]:          0 :             if (bClosed) { // "pear problem": 2 lines, 1 curve, everything smoothed, a point between both lines is dragged
    1248 [ #  # ][ #  # ]:          0 :                 if (aXPoly.GetPointCount()>nPntAnz && aXPoly.IsControl(1)) {
         [ #  # ][ #  # ]
                 [ #  # ]
    1249         [ #  # ]:          0 :                     sal_uInt16 a=aXPoly.GetPointCount();
    1250 [ #  # ][ #  # ]:          0 :                     aXPoly[a-2]=aXPoly[2]; aXPoly.SetFlags(a-2,aXPoly.GetFlags(2));
         [ #  # ][ #  # ]
    1251 [ #  # ][ #  # ]:          0 :                     aXPoly[a-1]=aXPoly[3]; aXPoly.SetFlags(a-1,aXPoly.GetFlags(3));
         [ #  # ][ #  # ]
    1252         [ #  # ]:          0 :                     aXPoly.Remove(0,3);
    1253                 :            :                 }
    1254                 :            :             }
    1255                 :            :         }
    1256         [ #  # ]:          0 :         aRetval.Insert(aXPoly);
    1257 [ #  # ][ #  # ]:          0 :         if (aLine1.GetPointCount()>1) aRetval.Insert(aLine1);
                 [ #  # ]
    1258 [ #  # ][ #  # ]:          0 :         if (aLine2.GetPointCount()>1) aRetval.Insert(aLine2);
                 [ #  # ]
    1259 [ #  # ][ #  # ]:          0 :         if (aLine3.GetPointCount()>1) aRetval.Insert(aLine3);
                 [ #  # ]
    1260 [ #  # ][ #  # ]:          0 :         if (aLine4.GetPointCount()>1) aRetval.Insert(aLine4);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1261                 :            :     }
    1262                 :            : 
    1263 [ #  # ][ #  # ]:          0 :     return aRetval.getB2DPolyPolygon();
    1264                 :            : }
    1265                 :            : 
    1266                 :          0 : bool ImpPathForDragAndCreate::BegCreate(SdrDragStat& rStat)
    1267                 :            : {
    1268                 :          0 :     bool bFreeHand(IsFreeHand(meObjectKind));
    1269                 :          0 :     rStat.SetNoSnap(bFreeHand);
    1270                 :          0 :     rStat.SetOrtho8Possible();
    1271                 :          0 :     aPathPolygon.Clear();
    1272                 :          0 :     mbCreating=sal_True;
    1273                 :          0 :     bool bMakeStartPoint = true;
    1274                 :          0 :     SdrView* pView=rStat.GetView();
    1275 [ #  # ][ #  # ]:          0 :     if (pView!=NULL && pView->IsUseIncompatiblePathCreateInterface() &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1276                 :            :         (meObjectKind==OBJ_POLY || meObjectKind==OBJ_PLIN || meObjectKind==OBJ_PATHLINE || meObjectKind==OBJ_PATHFILL)) {
    1277                 :          0 :         bMakeStartPoint = false;
    1278                 :            :     }
    1279         [ #  # ]:          0 :     aPathPolygon.Insert(XPolygon());
    1280                 :          0 :     aPathPolygon[0][0]=rStat.GetStart();
    1281         [ #  # ]:          0 :     if (bMakeStartPoint) {
    1282                 :          0 :         aPathPolygon[0][1]=rStat.GetNow();
    1283                 :            :     }
    1284                 :          0 :     ImpPathCreateUser* pU=new ImpPathCreateUser;
    1285                 :          0 :     pU->eStartKind=meObjectKind;
    1286                 :          0 :     pU->eAktKind=meObjectKind;
    1287                 :          0 :     rStat.SetUser(pU);
    1288                 :          0 :     return true;
    1289                 :            : }
    1290                 :            : 
    1291                 :          0 : bool ImpPathForDragAndCreate::MovCreate(SdrDragStat& rStat)
    1292                 :            : {
    1293                 :          0 :     ImpPathCreateUser* pU=(ImpPathCreateUser*)rStat.GetUser();
    1294                 :          0 :     SdrView* pView=rStat.GetView();
    1295                 :          0 :     XPolygon& rXPoly=aPathPolygon[aPathPolygon.Count()-1];
    1296 [ #  # ][ #  # ]:          0 :     if (pView!=NULL && pView->IsCreateMode()) {
                 [ #  # ]
    1297                 :            :         // switch to different CreateTool, if appropriate
    1298                 :            :         sal_uInt16 nIdent;
    1299                 :            :         sal_uInt32 nInvent;
    1300                 :          0 :         pView->TakeCurrentObj(nIdent,nInvent);
    1301 [ #  # ][ #  # ]:          0 :         if (nInvent==SdrInventor && pU->eAktKind!=(SdrObjKind)nIdent) {
    1302                 :          0 :             SdrObjKind eNewKind=(SdrObjKind)nIdent;
    1303      [ #  #  # ]:          0 :             switch (eNewKind) {
    1304                 :          0 :                 case OBJ_CARC: case OBJ_CIRC: case OBJ_CCUT: case OBJ_SECT: eNewKind=OBJ_CARC;
    1305                 :            :                 case OBJ_RECT:
    1306                 :            :                 case OBJ_LINE: case OBJ_PLIN: case OBJ_POLY:
    1307                 :            :                 case OBJ_PATHLINE: case OBJ_PATHFILL:
    1308                 :            :                 case OBJ_FREELINE: case OBJ_FREEFILL:
    1309                 :            :                 case OBJ_SPLNLINE: case OBJ_SPLNFILL: {
    1310                 :          0 :                     pU->eAktKind=eNewKind;
    1311                 :          0 :                     pU->bMixedCreate=sal_True;
    1312         [ #  # ]:          0 :                     pU->nBezierStartPoint=rXPoly.GetPointCount();
    1313         [ #  # ]:          0 :                     if (pU->nBezierStartPoint>0) pU->nBezierStartPoint--;
    1314                 :          0 :                 } break;
    1315                 :          0 :                 default: break;
    1316                 :            :             } // switch
    1317                 :            :         }
    1318                 :            :     }
    1319                 :          0 :     sal_uInt16 nActPoint=rXPoly.GetPointCount();
    1320 [ #  # ][ #  # ]:          0 :     if (aPathPolygon.Count()>1 && rStat.IsMouseDown() && nActPoint<2) {
         [ #  # ][ #  # ]
    1321                 :          0 :         rXPoly[0]=rStat.GetPos0();
    1322                 :          0 :         rXPoly[1]=rStat.GetNow();
    1323                 :          0 :         nActPoint=2;
    1324                 :            :     }
    1325         [ #  # ]:          0 :     if (nActPoint==0) {
    1326                 :          0 :         rXPoly[0]=rStat.GetPos0();
    1327                 :          0 :     } else nActPoint--;
    1328                 :          0 :     bool bFreeHand=IsFreeHand(pU->eAktKind);
    1329                 :          0 :     rStat.SetNoSnap(bFreeHand);
    1330 [ #  # ][ #  # ]:          0 :     rStat.SetOrtho8Possible(pU->eAktKind!=OBJ_CARC && pU->eAktKind!=OBJ_RECT && (!pU->bMixedCreate || pU->eAktKind!=OBJ_LINE));
         [ #  # ][ #  # ]
    1331                 :          0 :     rXPoly[nActPoint]=rStat.Now();
    1332 [ #  # ][ #  # ]:          0 :     if (!pU->bMixedCreate && pU->eStartKind==OBJ_LINE && rXPoly.GetPointCount()>=1) {
         [ #  # ][ #  # ]
    1333         [ #  # ]:          0 :         Point aPt(rStat.Start());
    1334 [ #  # ][ #  # ]:          0 :         if (pView!=NULL && pView->IsCreate1stPointAsCenter()) {
                 [ #  # ]
    1335                 :          0 :             aPt+=aPt;
    1336         [ #  # ]:          0 :             aPt-=rStat.Now();
    1337                 :            :         }
    1338         [ #  # ]:          0 :         rXPoly[0]=aPt;
    1339                 :            :     }
    1340         [ #  # ]:          0 :     OutputDevice* pOut=pView==NULL ? NULL : pView->GetFirstOutputDevice();
    1341         [ #  # ]:          0 :     if (bFreeHand) {
    1342         [ #  # ]:          0 :         if (pU->nBezierStartPoint>nActPoint) pU->nBezierStartPoint=nActPoint;
    1343 [ #  # ][ #  # ]:          0 :         if (rStat.IsMouseDown() && nActPoint>0) {
                 [ #  # ]
    1344                 :            :             // don't allow two consecutive points to occupy too similar positions
    1345                 :          0 :             long nMinDist=1;
    1346         [ #  # ]:          0 :             if (pView!=NULL) nMinDist=pView->GetFreeHandMinDistPix();
    1347 [ #  # ][ #  # ]:          0 :             if (pOut!=NULL) nMinDist=pOut->PixelToLogic(Size(nMinDist,0)).Width();
    1348         [ #  # ]:          0 :             if (nMinDist<1) nMinDist=1;
    1349                 :            : 
    1350         [ #  # ]:          0 :             Point aPt0(rXPoly[nActPoint-1]);
    1351         [ #  # ]:          0 :             Point aPt1(rStat.Now());
    1352         [ #  # ]:          0 :             long dx=aPt0.X()-aPt1.X(); if (dx<0) dx=-dx;
    1353         [ #  # ]:          0 :             long dy=aPt0.Y()-aPt1.Y(); if (dy<0) dy=-dy;
    1354 [ #  # ][ #  # ]:          0 :             if (dx<nMinDist && dy<nMinDist) return sal_False;
    1355                 :            : 
    1356                 :            :             // TODO: the following is copied from EndCreate (with a few smaller modifications)
    1357                 :            :             // and should be combined into a method with the code there.
    1358                 :            : 
    1359 [ #  # ][ #  # ]:          0 :             if (nActPoint-pU->nBezierStartPoint>=3 && ((nActPoint-pU->nBezierStartPoint)%3)==0) {
    1360         [ #  # ]:          0 :                 rXPoly.PointsToBezier(nActPoint-3);
    1361         [ #  # ]:          0 :                 rXPoly.SetFlags(nActPoint-1,XPOLY_CONTROL);
    1362         [ #  # ]:          0 :                 rXPoly.SetFlags(nActPoint-2,XPOLY_CONTROL);
    1363                 :            : 
    1364 [ #  # ][ #  # ]:          0 :                 if (nActPoint>=6 && rXPoly.IsControl(nActPoint-4)) {
         [ #  # ][ #  # ]
    1365         [ #  # ]:          0 :                     rXPoly.CalcTangent(nActPoint-3,nActPoint-4,nActPoint-2);
    1366         [ #  # ]:          0 :                     rXPoly.SetFlags(nActPoint-3,XPOLY_SMOOTH);
    1367                 :            :                 }
    1368                 :            :             }
    1369 [ #  # ][ #  # ]:          0 :             rXPoly[nActPoint+1]=rStat.Now();
    1370         [ #  # ]:          0 :             rStat.NextPoint();
    1371                 :            :         } else {
    1372                 :          0 :             pU->nBezierStartPoint=nActPoint;
    1373                 :            :         }
    1374                 :            :     }
    1375                 :            : 
    1376                 :          0 :     pU->ResetFormFlags();
    1377         [ #  # ]:          0 :     if (IsBezier(pU->eAktKind)) {
    1378         [ #  # ]:          0 :         if (nActPoint>=2) {
    1379 [ #  # ][ #  # ]:          0 :             pU->CalcBezier(rXPoly[nActPoint-1],rXPoly[nActPoint],rXPoly[nActPoint-1]-rXPoly[nActPoint-2],rStat.IsMouseDown());
    1380         [ #  # ]:          0 :         } else if (pU->bBezHasCtrl0) {
    1381 [ #  # ][ #  # ]:          0 :             pU->CalcBezier(rXPoly[nActPoint-1],rXPoly[nActPoint],pU->aBezControl0-rXPoly[nActPoint-1],rStat.IsMouseDown());
    1382                 :            :         }
    1383                 :            :     }
    1384 [ #  # ][ #  # ]:          0 :     if (pU->eAktKind==OBJ_CARC && nActPoint>=2) {
    1385 [ #  # ][ #  # ]:          0 :         pU->CalcCircle(rXPoly[nActPoint-1],rXPoly[nActPoint],rXPoly[nActPoint-1]-rXPoly[nActPoint-2],pView);
                 [ #  # ]
    1386                 :            :     }
    1387 [ #  # ][ #  # ]:          0 :     if (pU->eAktKind==OBJ_LINE && nActPoint>=2) {
    1388 [ #  # ][ #  # ]:          0 :         pU->CalcLine(rXPoly[nActPoint-1],rXPoly[nActPoint],rXPoly[nActPoint-1]-rXPoly[nActPoint-2],pView);
                 [ #  # ]
    1389                 :            :     }
    1390 [ #  # ][ #  # ]:          0 :     if (pU->eAktKind==OBJ_RECT && nActPoint>=2) {
    1391 [ #  # ][ #  # ]:          0 :         pU->CalcRect(rXPoly[nActPoint-1],rXPoly[nActPoint],rXPoly[nActPoint-1]-rXPoly[nActPoint-2],pView);
                 [ #  # ]
    1392                 :            :     }
    1393                 :            : 
    1394                 :          0 :     return true;
    1395                 :            : }
    1396                 :            : 
    1397                 :          0 : bool ImpPathForDragAndCreate::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
    1398                 :            : {
    1399                 :          0 :     ImpPathCreateUser* pU=(ImpPathCreateUser*)rStat.GetUser();
    1400                 :          0 :     bool bRet = false;
    1401                 :          0 :     SdrView* pView=rStat.GetView();
    1402 [ #  # ][ #  # ]:          0 :     bool bIncomp=pView!=NULL && pView->IsUseIncompatiblePathCreateInterface();
    1403                 :          0 :     XPolygon& rXPoly=aPathPolygon[aPathPolygon.Count()-1];
    1404                 :          0 :     sal_uInt16 nActPoint=rXPoly.GetPointCount()-1;
    1405                 :          0 :     rXPoly[nActPoint]=rStat.Now();
    1406 [ #  # ][ #  # ]:          0 :     if (!pU->bMixedCreate && pU->eStartKind==OBJ_LINE) {
    1407         [ #  # ]:          0 :         if (rStat.GetPointAnz()>=2) eCmd=SDRCREATE_FORCEEND;
    1408                 :          0 :         bRet = eCmd==SDRCREATE_FORCEEND;
    1409         [ #  # ]:          0 :         if (bRet) {
    1410                 :          0 :             mbCreating = sal_False;
    1411                 :          0 :             delete pU;
    1412                 :          0 :             rStat.SetUser(NULL);
    1413                 :            :         }
    1414                 :          0 :         return bRet;
    1415                 :            :     }
    1416                 :            : 
    1417 [ #  # ][ #  # ]:          0 :     if (!pU->bMixedCreate && IsFreeHand(pU->eStartKind)) {
                 [ #  # ]
    1418         [ #  # ]:          0 :         if (rStat.GetPointAnz()>=2) eCmd=SDRCREATE_FORCEEND;
    1419                 :          0 :         bRet=eCmd==SDRCREATE_FORCEEND;
    1420         [ #  # ]:          0 :         if (bRet) {
    1421                 :          0 :             mbCreating=sal_False;
    1422                 :          0 :             delete pU;
    1423                 :          0 :             rStat.SetUser(NULL);
    1424                 :            :         }
    1425                 :          0 :         return bRet;
    1426                 :            :     }
    1427 [ #  # ][ #  # ]:          0 :     if (eCmd==SDRCREATE_NEXTPOINT || eCmd==SDRCREATE_NEXTOBJECT) {
    1428                 :            :         // don't allow two consecutive points to occupy the same position
    1429 [ #  # ][ #  # ]:          0 :         if (nActPoint==0 || rStat.Now()!=rXPoly[nActPoint-1]) {
                 [ #  # ]
    1430         [ #  # ]:          0 :             if (bIncomp) {
    1431         [ #  # ]:          0 :                 if (pU->nBezierStartPoint>nActPoint) pU->nBezierStartPoint=nActPoint;
    1432 [ #  # ][ #  # ]:          0 :                 if (IsBezier(pU->eAktKind) && nActPoint-pU->nBezierStartPoint>=3 && ((nActPoint-pU->nBezierStartPoint)%3)==0) {
         [ #  # ][ #  # ]
    1433                 :          0 :                     rXPoly.PointsToBezier(nActPoint-3);
    1434                 :          0 :                     rXPoly.SetFlags(nActPoint-1,XPOLY_CONTROL);
    1435                 :          0 :                     rXPoly.SetFlags(nActPoint-2,XPOLY_CONTROL);
    1436                 :            : 
    1437 [ #  # ][ #  # ]:          0 :                     if (nActPoint>=6 && rXPoly.IsControl(nActPoint-4)) {
                 [ #  # ]
    1438                 :          0 :                         rXPoly.CalcTangent(nActPoint-3,nActPoint-4,nActPoint-2);
    1439                 :          0 :                         rXPoly.SetFlags(nActPoint-3,XPOLY_SMOOTH);
    1440                 :            :                     }
    1441                 :            :                 }
    1442                 :            :             } else {
    1443 [ #  # ][ #  # ]:          0 :                 if (nActPoint==1 && IsBezier(pU->eAktKind) && !pU->bBezHasCtrl0) {
         [ #  # ][ #  # ]
    1444                 :          0 :                     pU->aBezControl0=rStat.GetNow();
    1445                 :          0 :                     pU->bBezHasCtrl0=sal_True;
    1446                 :          0 :                     nActPoint--;
    1447                 :            :                 }
    1448         [ #  # ]:          0 :                 if (pU->IsFormFlag()) {
    1449                 :          0 :                     sal_uInt16 nPtAnz0=rXPoly.GetPointCount();
    1450                 :          0 :                     rXPoly.Remove(nActPoint-1,2); // remove last two points and replace by form
    1451         [ #  # ]:          0 :                     rXPoly.Insert(XPOLY_APPEND,pU->GetFormPoly());
    1452                 :          0 :                     sal_uInt16 nPtAnz1=rXPoly.GetPointCount();
    1453         [ #  # ]:          0 :                     for (sal_uInt16 i=nPtAnz0+1; i<nPtAnz1-1; i++) { // to make BckAction work
    1454         [ #  # ]:          0 :                         if (!rXPoly.IsControl(i)) rStat.NextPoint();
    1455                 :            :                     }
    1456                 :          0 :                     nActPoint=rXPoly.GetPointCount()-1;
    1457                 :            :                 }
    1458                 :            :             }
    1459                 :          0 :             nActPoint++;
    1460                 :          0 :             rXPoly[nActPoint]=rStat.GetNow();
    1461                 :            :         }
    1462         [ #  # ]:          0 :         if (eCmd==SDRCREATE_NEXTOBJECT) {
    1463         [ #  # ]:          0 :             if (rXPoly.GetPointCount()>=2) {
    1464                 :          0 :                 pU->bBezHasCtrl0=sal_False;
    1465                 :            :                 // only a singular polygon may be opened, so close this
    1466 [ #  # ][ #  # ]:          0 :                 rXPoly[nActPoint]=rXPoly[0];
    1467         [ #  # ]:          0 :                 XPolygon aXP;
    1468 [ #  # ][ #  # ]:          0 :                 aXP[0]=rStat.GetNow();
    1469 [ #  # ][ #  # ]:          0 :                 aPathPolygon.Insert(aXP);
    1470                 :            :             }
    1471                 :            :         }
    1472                 :            :     }
    1473                 :            : 
    1474                 :          0 :     sal_uInt16 nPolyAnz=aPathPolygon.Count();
    1475         [ #  # ]:          0 :     if (nPolyAnz!=0) {
    1476                 :            :         // delete last point, if necessary
    1477         [ #  # ]:          0 :         if (eCmd==SDRCREATE_FORCEEND) {
    1478                 :          0 :             XPolygon& rXP=aPathPolygon[nPolyAnz-1];
    1479                 :          0 :             sal_uInt16 nPtAnz=rXP.GetPointCount();
    1480         [ #  # ]:          0 :             if (nPtAnz>=2) {
    1481         [ #  # ]:          0 :                 if (!rXP.IsControl(nPtAnz-2)) {
    1482         [ #  # ]:          0 :                     if (rXP[nPtAnz-1]==rXP[nPtAnz-2]) {
    1483                 :          0 :                         rXP.Remove(nPtAnz-1,1);
    1484                 :            :                     }
    1485                 :            :                 } else {
    1486         [ #  # ]:          0 :                     if (rXP[nPtAnz-3]==rXP[nPtAnz-2]) {
    1487                 :          0 :                         rXP.Remove(nPtAnz-3,3);
    1488                 :            :                     }
    1489                 :            :                 }
    1490                 :            :             }
    1491                 :            :         }
    1492         [ #  # ]:          0 :         for (sal_uInt16 nPolyNum=nPolyAnz; nPolyNum>0;) {
    1493                 :          0 :             nPolyNum--;
    1494                 :          0 :             XPolygon& rXP=aPathPolygon[nPolyNum];
    1495                 :          0 :             sal_uInt16 nPtAnz=rXP.GetPointCount();
    1496                 :            :             // delete polygons with too few points
    1497 [ #  # ][ #  # ]:          0 :             if (nPolyNum<nPolyAnz-1 || eCmd==SDRCREATE_FORCEEND) {
    1498         [ #  # ]:          0 :                 if (nPtAnz<2) aPathPolygon.Remove(nPolyNum);
    1499                 :            :             }
    1500                 :            :         }
    1501                 :            :     }
    1502                 :          0 :     pU->ResetFormFlags();
    1503                 :          0 :     bRet=eCmd==SDRCREATE_FORCEEND;
    1504         [ #  # ]:          0 :     if (bRet) {
    1505                 :          0 :         mbCreating=sal_False;
    1506                 :          0 :         delete pU;
    1507                 :          0 :         rStat.SetUser(NULL);
    1508                 :            :     }
    1509                 :          0 :     return bRet;
    1510                 :            : }
    1511                 :            : 
    1512                 :          0 : bool ImpPathForDragAndCreate::BckCreate(SdrDragStat& rStat)
    1513                 :            : {
    1514                 :          0 :     ImpPathCreateUser* pU=(ImpPathCreateUser*)rStat.GetUser();
    1515         [ #  # ]:          0 :     if (aPathPolygon.Count()>0) {
    1516                 :          0 :         XPolygon& rXPoly=aPathPolygon[aPathPolygon.Count()-1];
    1517                 :          0 :         sal_uInt16 nActPoint=rXPoly.GetPointCount();
    1518         [ #  # ]:          0 :         if (nActPoint>0) {
    1519                 :          0 :             nActPoint--;
    1520                 :            :             // make the last part of a bezier curve a line
    1521                 :          0 :             rXPoly.Remove(nActPoint,1);
    1522 [ #  # ][ #  # ]:          0 :             if (nActPoint>=3 && rXPoly.IsControl(nActPoint-1)) {
                 [ #  # ]
    1523                 :            :                 // there should never be a bezier segment at the end, so this is just in case...
    1524                 :          0 :                 rXPoly.Remove(nActPoint-1,1);
    1525         [ #  # ]:          0 :                 if (rXPoly.IsControl(nActPoint-2)) rXPoly.Remove(nActPoint-2,1);
    1526                 :            :             }
    1527                 :            :         }
    1528                 :          0 :         nActPoint=rXPoly.GetPointCount();
    1529         [ #  # ]:          0 :         if (nActPoint>=4) { // no bezier segment at the end
    1530                 :          0 :             nActPoint--;
    1531         [ #  # ]:          0 :             if (rXPoly.IsControl(nActPoint-1)) {
    1532                 :          0 :                 rXPoly.Remove(nActPoint-1,1);
    1533         [ #  # ]:          0 :                 if (rXPoly.IsControl(nActPoint-2)) rXPoly.Remove(nActPoint-2,1);
    1534                 :            :             }
    1535                 :            :         }
    1536         [ #  # ]:          0 :         if (rXPoly.GetPointCount()<2) {
    1537                 :          0 :             aPathPolygon.Remove(aPathPolygon.Count()-1);
    1538                 :            :         }
    1539         [ #  # ]:          0 :         if (aPathPolygon.Count()>0) {
    1540                 :          0 :             XPolygon& rLocalXPoly=aPathPolygon[aPathPolygon.Count()-1];
    1541                 :          0 :             sal_uInt16 nLocalActPoint=rLocalXPoly.GetPointCount();
    1542         [ #  # ]:          0 :             if (nLocalActPoint>0) {
    1543                 :          0 :                 nLocalActPoint--;
    1544                 :          0 :                 rLocalXPoly[nLocalActPoint]=rStat.Now();
    1545                 :            :             }
    1546                 :            :         }
    1547                 :            :     }
    1548                 :          0 :     pU->ResetFormFlags();
    1549                 :          0 :     return aPathPolygon.Count()!=0;
    1550                 :            : }
    1551                 :            : 
    1552                 :          0 : void ImpPathForDragAndCreate::BrkCreate(SdrDragStat& rStat)
    1553                 :            : {
    1554                 :          0 :     ImpPathCreateUser* pU=(ImpPathCreateUser*)rStat.GetUser();
    1555                 :          0 :     aPathPolygon.Clear();
    1556                 :          0 :     mbCreating=sal_False;
    1557                 :          0 :     delete pU;
    1558                 :          0 :     rStat.SetUser(NULL);
    1559                 :          0 : }
    1560                 :            : 
    1561                 :          0 : basegfx::B2DPolyPolygon ImpPathForDragAndCreate::TakeObjectPolyPolygon(const SdrDragStat& rDrag) const
    1562                 :            : {
    1563         [ #  # ]:          0 :     basegfx::B2DPolyPolygon aRetval(aPathPolygon.getB2DPolyPolygon());
    1564                 :          0 :     SdrView* pView = rDrag.GetView();
    1565                 :            : 
    1566 [ #  # ][ #  # ]:          0 :     if(pView && pView->IsUseIncompatiblePathCreateInterface())
                 [ #  # ]
    1567                 :            :         return aRetval;
    1568                 :            : 
    1569                 :          0 :     ImpPathCreateUser* pU = (ImpPathCreateUser*)rDrag.GetUser();
    1570 [ #  # ][ #  # ]:          0 :     basegfx::B2DPolygon aNewPolygon(aRetval.count() ? aRetval.getB2DPolygon(aRetval.count() - 1L) : basegfx::B2DPolygon());
         [ #  # ][ #  # ]
                 [ #  # ]
    1571                 :            : 
    1572 [ #  # ][ #  # ]:          0 :     if(pU->IsFormFlag() && aNewPolygon.count() > 1L)
         [ #  # ][ #  # ]
    1573                 :            :     {
    1574                 :            :         // remove last segment and replace with current
    1575                 :            :         // do not forget to rescue the previous control point which will be lost when
    1576                 :            :         // the point it's associated with is removed
    1577         [ #  # ]:          0 :         const sal_uInt32 nChangeIndex(aNewPolygon.count() - 2);
    1578         [ #  # ]:          0 :         const basegfx::B2DPoint aSavedPrevCtrlPoint(aNewPolygon.getPrevControlPoint(nChangeIndex));
    1579                 :            : 
    1580         [ #  # ]:          0 :         aNewPolygon.remove(nChangeIndex, 2L);
    1581 [ #  # ][ #  # ]:          0 :         aNewPolygon.append(pU->GetFormPoly().getB2DPolygon());
         [ #  # ][ #  # ]
                 [ #  # ]
    1582                 :            : 
    1583 [ #  # ][ #  # ]:          0 :         if(nChangeIndex < aNewPolygon.count())
    1584                 :            :         {
    1585                 :            :             // if really something was added, set the saved previous control point to the
    1586                 :            :             // point where it belongs
    1587         [ #  # ]:          0 :             aNewPolygon.setPrevControlPoint(nChangeIndex, aSavedPrevCtrlPoint);
    1588                 :          0 :         }
    1589                 :            :     }
    1590                 :            : 
    1591 [ #  # ][ #  # ]:          0 :     if(aRetval.count())
    1592                 :            :     {
    1593 [ #  # ][ #  # ]:          0 :         aRetval.setB2DPolygon(aRetval.count() - 1L, aNewPolygon);
    1594                 :            :     }
    1595                 :            :     else
    1596                 :            :     {
    1597         [ #  # ]:          0 :         aRetval.append(aNewPolygon);
    1598                 :            :     }
    1599                 :            : 
    1600         [ #  # ]:          0 :     return aRetval;
    1601                 :            : }
    1602                 :            : 
    1603                 :          0 : basegfx::B2DPolyPolygon ImpPathForDragAndCreate::TakeDragPolyPolygon(const SdrDragStat& rDrag) const
    1604                 :            : {
    1605                 :          0 :     basegfx::B2DPolyPolygon aRetval;
    1606                 :          0 :     SdrView* pView = rDrag.GetView();
    1607                 :            : 
    1608 [ #  # ][ #  # ]:          0 :     if(pView && pView->IsUseIncompatiblePathCreateInterface())
                 [ #  # ]
    1609                 :          0 :         return aRetval;
    1610                 :            : 
    1611                 :          0 :     ImpPathCreateUser* pU = (ImpPathCreateUser*)rDrag.GetUser();
    1612                 :            : 
    1613 [ #  # ][ #  # ]:          0 :     if(pU && pU->bBezier && rDrag.IsMouseDown())
         [ #  # ][ #  # ]
    1614                 :            :     {
    1615                 :            :         // no more XOR, no need for complicated helplines
    1616         [ #  # ]:          0 :         basegfx::B2DPolygon aHelpline;
    1617         [ #  # ]:          0 :         aHelpline.append(basegfx::B2DPoint(pU->aBezCtrl2.X(), pU->aBezCtrl2.Y()));
    1618         [ #  # ]:          0 :         aHelpline.append(basegfx::B2DPoint(pU->aBezEnd.X(), pU->aBezEnd.Y()));
    1619 [ #  # ][ #  # ]:          0 :         aRetval.append(aHelpline);
    1620                 :            :     }
    1621                 :            : 
    1622                 :          0 :     return aRetval;
    1623                 :            : }
    1624                 :            : 
    1625                 :          0 : Pointer ImpPathForDragAndCreate::GetCreatePointer() const
    1626                 :            : {
    1627   [ #  #  #  #  :          0 :     switch (meObjectKind) {
          #  #  #  #  #  
                #  #  # ]
    1628                 :          0 :         case OBJ_LINE    : return Pointer(POINTER_DRAW_LINE);
    1629                 :          0 :         case OBJ_POLY    : return Pointer(POINTER_DRAW_POLYGON);
    1630                 :          0 :         case OBJ_PLIN    : return Pointer(POINTER_DRAW_POLYGON);
    1631                 :          0 :         case OBJ_PATHLINE: return Pointer(POINTER_DRAW_BEZIER);
    1632                 :          0 :         case OBJ_PATHFILL: return Pointer(POINTER_DRAW_BEZIER);
    1633                 :          0 :         case OBJ_FREELINE: return Pointer(POINTER_DRAW_FREEHAND);
    1634                 :          0 :         case OBJ_FREEFILL: return Pointer(POINTER_DRAW_FREEHAND);
    1635                 :          0 :         case OBJ_SPLNLINE: return Pointer(POINTER_DRAW_FREEHAND);
    1636                 :          0 :         case OBJ_SPLNFILL: return Pointer(POINTER_DRAW_FREEHAND);
    1637                 :          0 :         case OBJ_PATHPOLY: return Pointer(POINTER_DRAW_POLYGON);
    1638                 :          0 :         case OBJ_PATHPLIN: return Pointer(POINTER_DRAW_POLYGON);
    1639                 :          0 :         default: break;
    1640                 :            :     } // switch
    1641                 :          0 :     return Pointer(POINTER_CROSS);
    1642                 :            : }
    1643                 :            : 
    1644                 :            : /*************************************************************************/
    1645                 :            : 
    1646         [ #  # ]:          0 : SdrPathObjGeoData::SdrPathObjGeoData()
    1647                 :            : {
    1648                 :          0 : }
    1649                 :            : 
    1650         [ #  # ]:          0 : SdrPathObjGeoData::~SdrPathObjGeoData()
    1651                 :            : {
    1652         [ #  # ]:          0 : }
    1653                 :            : 
    1654                 :            : //////////////////////////////////////////////////////////////////////////////
    1655                 :            : // DrawContact section
    1656                 :            : 
    1657                 :      19551 : sdr::contact::ViewContact* SdrPathObj::CreateObjectSpecificViewContact()
    1658                 :            : {
    1659         [ +  - ]:      19551 :     return new sdr::contact::ViewContactOfSdrPathObj(*this);
    1660                 :            : }
    1661                 :            : 
    1662                 :            : /*************************************************************************/
    1663                 :            : 
    1664 [ +  + ][ +  + ]:     970578 : TYPEINIT1(SdrPathObj,SdrTextObj);
    1665                 :            : 
    1666                 :      17283 : SdrPathObj::SdrPathObj(SdrObjKind eNewKind)
    1667                 :            : :   meKind(eNewKind),
    1668                 :            :     mpDAC(0L),
    1669         [ +  - ]:      17283 :     mdBrightness(1.0)
    1670                 :            : {
    1671                 :      17283 :     bClosedObj = IsClosed();
    1672                 :      17283 : }
    1673                 :            : 
    1674                 :       2268 : SdrPathObj::SdrPathObj(SdrObjKind eNewKind, const basegfx::B2DPolyPolygon& rPathPoly, double dBrightness)
    1675                 :            : :   maPathPolygon(rPathPoly),
    1676                 :            :     meKind(eNewKind),
    1677                 :            :     mpDAC(0L),
    1678         [ +  - ]:       2268 :     mdBrightness(dBrightness)
    1679                 :            : {
    1680                 :       2268 :     bClosedObj = IsClosed();
    1681         [ +  - ]:       2268 :     ImpForceKind();
    1682                 :       2268 : }
    1683                 :            : 
    1684         [ +  - ]:      19536 : SdrPathObj::~SdrPathObj()
    1685                 :            : {
    1686         [ +  - ]:      19536 :     impDeleteDAC();
    1687         [ -  + ]:      39072 : }
    1688                 :            : 
    1689                 :      12681 : sal_Bool ImpIsLine(const basegfx::B2DPolyPolygon& rPolyPolygon)
    1690                 :            : {
    1691 [ +  - ][ +  + ]:      12681 :     return (1L == rPolyPolygon.count() && 2L == rPolyPolygon.getB2DPolygon(0L).count());
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
                 [ #  # ]
    1692                 :            : }
    1693                 :            : 
    1694                 :      30682 : Rectangle ImpGetBoundRect(const basegfx::B2DPolyPolygon& rPolyPolygon)
    1695                 :            : {
    1696         [ +  - ]:      30682 :     basegfx::B2DRange aRange(basegfx::tools::getRange(rPolyPolygon));
    1697                 :            : 
    1698                 :            :     return Rectangle(
    1699                 :            :         FRound(aRange.getMinX()), FRound(aRange.getMinY()),
    1700 [ +  - ][ +  - ]:      30682 :         FRound(aRange.getMaxX()), FRound(aRange.getMaxY()));
         [ +  - ][ +  - ]
                 [ +  - ]
    1701                 :            : }
    1702                 :            : 
    1703                 :       4293 : void SdrPathObj::ImpForceLineWink()
    1704                 :            : {
    1705 [ +  - ][ +  - ]:       4293 :     if(OBJ_LINE == meKind && ImpIsLine(GetPathPoly()))
                 [ +  - ]
    1706                 :            :     {
    1707         [ +  - ]:       4293 :         const basegfx::B2DPolygon aPoly(GetPathPoly().getB2DPolygon(0L));
    1708         [ +  - ]:       4293 :         const basegfx::B2DPoint aB2DPoint0(aPoly.getB2DPoint(0L));
    1709         [ +  - ]:       4293 :         const basegfx::B2DPoint aB2DPoint1(aPoly.getB2DPoint(1L));
    1710                 :       4293 :         const Point aPoint0(FRound(aB2DPoint0.getX()), FRound(aB2DPoint0.getY()));
    1711                 :       4293 :         const Point aPoint1(FRound(aB2DPoint1.getX()), FRound(aB2DPoint1.getY()));
    1712                 :       4293 :         const Point aDelt(aPoint1 - aPoint0);
    1713                 :            : 
    1714         [ +  - ]:       4293 :         aGeo.nDrehWink=GetAngle(aDelt);
    1715                 :       4293 :         aGeo.nShearWink=0;
    1716         [ +  - ]:       4293 :         aGeo.RecalcSinCos();
    1717         [ +  - ]:       4293 :         aGeo.RecalcTan();
    1718                 :            : 
    1719                 :            :         // for SdrTextObj, keep aRect up to date
    1720         [ +  - ]:       4293 :         aRect = Rectangle(aPoint0, aPoint1);
    1721 [ +  - ][ +  - ]:       4293 :         aRect.Justify();
    1722                 :            :     }
    1723                 :       4293 : }
    1724                 :            : 
    1725                 :      19617 : void SdrPathObj::ImpForceKind()
    1726                 :            : {
    1727         [ -  + ]:      19617 :     if (meKind==OBJ_PATHPLIN) meKind=OBJ_PLIN;
    1728         [ -  + ]:      19617 :     if (meKind==OBJ_PATHPOLY) meKind=OBJ_POLY;
    1729                 :            : 
    1730         [ +  + ]:      19617 :     if(GetPathPoly().areControlPointsUsed())
    1731                 :            :     {
    1732   [ +  -  +  + ]:        312 :         switch (meKind)
    1733                 :            :         {
    1734                 :          6 :             case OBJ_LINE: meKind=OBJ_PATHLINE; break;
    1735                 :          0 :             case OBJ_PLIN: meKind=OBJ_PATHLINE; break;
    1736                 :         22 :             case OBJ_POLY: meKind=OBJ_PATHFILL; break;
    1737                 :        312 :             default: break;
    1738                 :            :         }
    1739                 :            :     }
    1740                 :            :     else
    1741                 :            :     {
    1742   [ +  -  +  -  :      19305 :         switch (meKind)
                      + ]
    1743                 :            :         {
    1744                 :         44 :             case OBJ_PATHLINE: meKind=OBJ_PLIN; break;
    1745                 :          0 :             case OBJ_FREELINE: meKind=OBJ_PLIN; break;
    1746                 :         36 :             case OBJ_PATHFILL: meKind=OBJ_POLY; break;
    1747                 :          0 :             case OBJ_FREEFILL: meKind=OBJ_POLY; break;
    1748                 :      19225 :             default: break;
    1749                 :            :         }
    1750                 :            :     }
    1751                 :            : 
    1752 [ +  + ][ -  + ]:      19617 :     if (meKind==OBJ_LINE && !ImpIsLine(GetPathPoly())) meKind=OBJ_PLIN;
                 [ -  + ]
    1753 [ +  + ][ +  + ]:      19617 :     if (meKind==OBJ_PLIN && ImpIsLine(GetPathPoly())) meKind=OBJ_LINE;
                 [ +  + ]
    1754                 :            : 
    1755                 :      19617 :     bClosedObj=IsClosed();
    1756                 :            : 
    1757         [ +  + ]:      19617 :     if (meKind==OBJ_LINE)
    1758                 :            :     {
    1759                 :       4293 :         ImpForceLineWink();
    1760                 :            :     }
    1761                 :            :     else
    1762                 :            :     {
    1763                 :            :         // #i10659#, for polys with more than 2 points.
    1764                 :            :         //
    1765                 :            :         // Here i again need to fix something, because when Path-Polys are Copy-Pasted
    1766                 :            :         // between Apps with different measurements (e.g. 100TH_MM and TWIPS) there is
    1767                 :            :         // a scaling loop started from SdrExchangeView::Paste. In itself, this is not
    1768                 :            :         // wrong, but aRect is wrong here and not even updated by RecalcSnapRect(). If
    1769                 :            :         // this is the case, some size needs to be set here in aRect to avoid that the cycle
    1770                 :            :         // through Rect2Poly - Poly2Rect does something badly wrong since that cycle is
    1771                 :            :         // BASED on aRect. That cycle is triggered in SdrTextObj::NbcResize() which is called
    1772                 :            :         // from the local Resize() implementation.
    1773                 :            :         //
    1774                 :            :         // Basic problem is that the member aRect in SdrTextObj basically is a unrotated
    1775                 :            :         // text rectangle for the text object itself and methods at SdrTextObj do handle it
    1776                 :            :         // in that way. Many draw objects derived from SdrTextObj 'abuse' aRect as SnapRect
    1777                 :            :         // which is basically wrong. To make the SdrText methods which deal with aRect directly
    1778                 :            :         // work it is necessary to always keep aRect updated. This e.g. not done after a Clone()
    1779                 :            :         // command for SdrPathObj. Since adding this update mechanism with #101412# to
    1780                 :            :         // ImpForceLineWink() for lines was very successful, i add it to where ImpForceLineWink()
    1781                 :            :         // was called, once here below and once on a 2nd place below.
    1782                 :            : 
    1783                 :            :         // #i10659# for SdrTextObj, keep aRect up to date
    1784         [ +  - ]:      15324 :         if(GetPathPoly().count())
    1785                 :            :         {
    1786                 :      15324 :             aRect = ImpGetBoundRect(GetPathPoly());
    1787                 :            :         }
    1788                 :            :     }
    1789                 :            : 
    1790                 :            :     // #i75974# adapt polygon state to object type. This may include a reinterpretation
    1791                 :            :     // of a closed geometry as open one, but with identical first and last point
    1792         [ +  + ]:      63502 :     for(sal_uInt32 a(0); a < maPathPolygon.count(); a++)
    1793                 :            :     {
    1794         [ +  - ]:      43885 :         basegfx::B2DPolygon aCandidate(maPathPolygon.getB2DPolygon(a));
    1795                 :            : 
    1796 [ +  - ][ +  + ]:      43885 :         if((bool)IsClosed() != aCandidate.isClosed())
    1797                 :            :         {
    1798                 :            :             // #i80213# really change polygon geometry; else e.g. the last point which
    1799                 :            :             // needs to be identical with the first one will be missing when opening
    1800                 :            :             // due to OBJ_PATH type
    1801 [ +  - ][ -  + ]:          9 :             if(aCandidate.isClosed())
    1802                 :            :             {
    1803         [ #  # ]:          0 :                 basegfx::tools::openWithGeometryChange(aCandidate);
    1804                 :            :             }
    1805                 :            :             else
    1806                 :            :             {
    1807         [ +  - ]:          9 :                 basegfx::tools::closeWithGeometryChange(aCandidate);
    1808                 :            :             }
    1809                 :            : 
    1810         [ +  - ]:          9 :             maPathPolygon.setB2DPolygon(a, aCandidate);
    1811                 :            :         }
    1812         [ +  - ]:      43885 :     }
    1813                 :      19617 : }
    1814                 :            : 
    1815                 :          0 : void SdrPathObj::ImpSetClosed(sal_Bool bClose)
    1816                 :            : {
    1817         [ #  # ]:          0 :     if(bClose)
    1818                 :            :     {
    1819   [ #  #  #  #  :          0 :         switch (meKind)
                   #  # ]
    1820                 :            :         {
    1821                 :          0 :             case OBJ_LINE    : meKind=OBJ_POLY;     break;
    1822                 :          0 :             case OBJ_PLIN    : meKind=OBJ_POLY;     break;
    1823                 :          0 :             case OBJ_PATHLINE: meKind=OBJ_PATHFILL; break;
    1824                 :          0 :             case OBJ_FREELINE: meKind=OBJ_FREEFILL; break;
    1825                 :          0 :             case OBJ_SPLNLINE: meKind=OBJ_SPLNFILL; break;
    1826                 :          0 :             default: break;
    1827                 :            :         }
    1828                 :            : 
    1829                 :          0 :         bClosedObj = sal_True;
    1830                 :            :     }
    1831                 :            :     else
    1832                 :            :     {
    1833   [ #  #  #  #  :          0 :         switch (meKind)
                      # ]
    1834                 :            :         {
    1835                 :          0 :             case OBJ_POLY    : meKind=OBJ_PLIN;     break;
    1836                 :          0 :             case OBJ_PATHFILL: meKind=OBJ_PATHLINE; break;
    1837                 :          0 :             case OBJ_FREEFILL: meKind=OBJ_FREELINE; break;
    1838                 :          0 :             case OBJ_SPLNFILL: meKind=OBJ_SPLNLINE; break;
    1839                 :          0 :             default: break;
    1840                 :            :         }
    1841                 :            : 
    1842                 :          0 :         bClosedObj = sal_False;
    1843                 :            :     }
    1844                 :            : 
    1845                 :          0 :     ImpForceKind();
    1846                 :          0 : }
    1847                 :            : 
    1848                 :         52 : void SdrPathObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
    1849                 :            : {
    1850                 :         52 :     rInfo.bNoContortion=sal_False;
    1851                 :            : 
    1852 [ -  + ][ #  # ]:         52 :     bool bCanConv = !HasText() || ImpCanConvTextToCurve();
    1853 [ -  + ][ #  # ]:         52 :     bool bIsPath = IsBezier() || IsSpline();
    1854                 :            : 
    1855                 :         52 :     rInfo.bEdgeRadiusAllowed    = sal_False;
    1856 [ +  - ][ -  + ]:         52 :     rInfo.bCanConvToPath = bCanConv && !bIsPath;
    1857 [ +  - ][ +  - ]:         52 :     rInfo.bCanConvToPoly = bCanConv && bIsPath;
    1858 [ +  - ][ -  + ]:         52 :     rInfo.bCanConvToContour = !IsFontwork() && (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
                 [ #  # ]
    1859                 :         52 : }
    1860                 :            : 
    1861                 :     159138 : sal_uInt16 SdrPathObj::GetObjIdentifier() const
    1862                 :            : {
    1863                 :     159138 :     return sal_uInt16(meKind);
    1864                 :            : }
    1865                 :            : 
    1866                 :          0 : SdrPathObj* SdrPathObj::Clone() const
    1867                 :            : {
    1868                 :          0 :     return CloneHelper< SdrPathObj >();
    1869                 :            : }
    1870                 :            : 
    1871                 :          0 : SdrPathObj& SdrPathObj::operator=(const SdrPathObj& rObj)
    1872                 :            : {
    1873         [ #  # ]:          0 :     if( this == &rObj )
    1874                 :          0 :         return *this;
    1875                 :          0 :     SdrTextObj::operator=(rObj);
    1876                 :          0 :     maPathPolygon=rObj.GetPathPoly();
    1877                 :          0 :     return *this;
    1878                 :            : }
    1879                 :            : 
    1880                 :        262 : void SdrPathObj::TakeObjNameSingul(XubString& rName) const
    1881                 :            : {
    1882         [ +  + ]:        262 :     if(OBJ_LINE == meKind)
    1883                 :            :     {
    1884                 :         52 :         sal_uInt16 nId(STR_ObjNameSingulLINE);
    1885                 :            : 
    1886 [ +  - ][ +  - ]:         52 :         if(ImpIsLine(GetPathPoly()))
    1887                 :            :         {
    1888         [ +  - ]:         52 :             const basegfx::B2DPolygon aPoly(GetPathPoly().getB2DPolygon(0L));
    1889         [ +  - ]:         52 :             const basegfx::B2DPoint aB2DPoint0(aPoly.getB2DPoint(0L));
    1890         [ +  - ]:         52 :             const basegfx::B2DPoint aB2DPoint1(aPoly.getB2DPoint(1L));
    1891                 :         52 :             const Point aPoint0(FRound(aB2DPoint0.getX()), FRound(aB2DPoint0.getY()));
    1892                 :         52 :             const Point aPoint1(FRound(aB2DPoint0.getX()), FRound(aB2DPoint0.getY()));
    1893                 :            : 
    1894         [ +  - ]:         52 :             if(aB2DPoint0 != aB2DPoint1)
    1895                 :            :             {
    1896         [ +  + ]:         52 :                 if(aB2DPoint0.getY() == aB2DPoint1.getY())
    1897                 :            :                 {
    1898                 :         14 :                     nId = STR_ObjNameSingulLINE_Hori;
    1899                 :            :                 }
    1900         [ +  + ]:         38 :                 else if(aB2DPoint0.getX() == aB2DPoint1.getX())
    1901                 :            :                 {
    1902                 :         10 :                     nId = STR_ObjNameSingulLINE_Vert;
    1903                 :            :                 }
    1904                 :            :                 else
    1905                 :            :                 {
    1906                 :         28 :                     const double fDx(fabs(aB2DPoint0.getX() - aB2DPoint1.getX()));
    1907                 :         28 :                     const double fDy(fabs(aB2DPoint0.getY() - aB2DPoint1.getY()));
    1908                 :            : 
    1909         [ -  + ]:         28 :                     if(fDx == fDy)
    1910                 :            :                     {
    1911                 :          0 :                         nId = STR_ObjNameSingulLINE_Diag;
    1912                 :            :                     }
    1913                 :            :                 }
    1914         [ +  - ]:         52 :             }
    1915                 :            :         }
    1916                 :            : 
    1917 [ +  - ][ +  - ]:         52 :         rName = ImpGetResStr(nId);
                 [ +  - ]
    1918                 :            :     }
    1919 [ +  - ][ +  + ]:        210 :     else if(OBJ_PLIN == meKind || OBJ_POLY == meKind)
    1920                 :            :     {
    1921                 :         26 :         const sal_Bool bClosed(OBJ_POLY == meKind);
    1922                 :         26 :         sal_uInt16 nId(0);
    1923                 :            : 
    1924 [ -  + ][ #  # ]:         26 :         if(mpDAC && mpDAC->IsCreating())
                 [ -  + ]
    1925                 :            :         {
    1926         [ #  # ]:          0 :             if(bClosed)
    1927                 :            :             {
    1928                 :          0 :                 nId = STR_ObjNameSingulPOLY;
    1929                 :            :             }
    1930                 :            :             else
    1931                 :            :             {
    1932                 :          0 :                 nId = STR_ObjNameSingulPLIN;
    1933                 :            :             }
    1934                 :            : 
    1935 [ #  # ][ #  # ]:          0 :             rName = ImpGetResStr(nId);
                 [ #  # ]
    1936                 :            :         }
    1937                 :            :         else
    1938                 :            :         {
    1939                 :            :             // get point count
    1940                 :         26 :             sal_uInt32 nPointCount(0L);
    1941         [ +  - ]:         26 :             const sal_uInt32 nPolyCount(GetPathPoly().count());
    1942                 :            : 
    1943         [ +  + ]:         52 :             for(sal_uInt32 a(0L); a < nPolyCount; a++)
    1944                 :            :             {
    1945 [ +  - ][ +  - ]:         26 :                 nPointCount += GetPathPoly().getB2DPolygon(a).count();
                 [ +  - ]
    1946                 :            :             }
    1947                 :            : 
    1948         [ +  - ]:         26 :             if(bClosed)
    1949                 :            :             {
    1950                 :         26 :                 nId = STR_ObjNameSingulPOLY_PntAnz;
    1951                 :            :             }
    1952                 :            :             else
    1953                 :            :             {
    1954                 :          0 :                 nId = STR_ObjNameSingulPLIN_PntAnz;
    1955                 :            :             }
    1956                 :            : 
    1957 [ +  - ][ +  - ]:         26 :             rName = ImpGetResStr(nId);
                 [ +  - ]
    1958         [ +  - ]:         26 :             sal_uInt16 nPos(rName.SearchAscii("%2")); // #i96537#
    1959                 :            : 
    1960         [ +  - ]:         26 :             if(STRING_NOTFOUND != nPos)
    1961                 :            :             {
    1962         [ +  - ]:         26 :                 rName.Erase(nPos, 2);
    1963 [ +  - ][ +  - ]:         26 :                 rName.Insert(rtl::OUString::valueOf(static_cast<sal_Int32>(nPointCount)), nPos);
                 [ +  - ]
    1964                 :            :             }
    1965                 :         26 :         }
    1966                 :            :     }
    1967                 :            :     else
    1968                 :            :     {
    1969   [ +  -  -  +  :        184 :         switch (meKind)
                -  -  - ]
    1970                 :            :         {
    1971 [ +  - ][ +  - ]:         84 :             case OBJ_PATHLINE: rName=ImpGetResStr(STR_ObjNameSingulPATHLINE); break;
                 [ +  - ]
    1972 [ #  # ][ #  # ]:          0 :             case OBJ_FREELINE: rName=ImpGetResStr(STR_ObjNameSingulFREELINE); break;
                 [ #  # ]
    1973 [ #  # ][ #  # ]:          0 :             case OBJ_SPLNLINE: rName=ImpGetResStr(STR_ObjNameSingulNATSPLN); break;
                 [ #  # ]
    1974 [ +  - ][ +  - ]:        100 :             case OBJ_PATHFILL: rName=ImpGetResStr(STR_ObjNameSingulPATHFILL); break;
                 [ +  - ]
    1975 [ #  # ][ #  # ]:          0 :             case OBJ_FREEFILL: rName=ImpGetResStr(STR_ObjNameSingulFREEFILL); break;
                 [ #  # ]
    1976 [ #  # ][ #  # ]:          0 :             case OBJ_SPLNFILL: rName=ImpGetResStr(STR_ObjNameSingulPERSPLN); break;
                 [ #  # ]
    1977                 :          0 :             default: break;
    1978                 :            :         }
    1979                 :            :     }
    1980                 :            : 
    1981 [ +  - ][ +  - ]:        262 :     String aName(GetName());
    1982         [ -  + ]:        262 :     if(aName.Len())
    1983                 :            :     {
    1984         [ #  # ]:          0 :         rName += sal_Unicode(' ');
    1985         [ #  # ]:          0 :         rName += sal_Unicode('\'');
    1986         [ #  # ]:          0 :         rName += aName;
    1987         [ #  # ]:          0 :         rName += sal_Unicode('\'');
    1988         [ +  - ]:        262 :     }
    1989                 :        262 : }
    1990                 :            : 
    1991                 :         64 : void SdrPathObj::TakeObjNamePlural(XubString& rName) const
    1992                 :            : {
    1993   [ +  -  +  +  :         64 :     switch(meKind)
          -  -  +  -  -  
                      - ]
    1994                 :            :     {
    1995         [ +  - ]:         12 :         case OBJ_LINE    : rName=ImpGetResStr(STR_ObjNamePluralLINE    ); break;
    1996         [ #  # ]:          0 :         case OBJ_PLIN    : rName=ImpGetResStr(STR_ObjNamePluralPLIN    ); break;
    1997         [ +  - ]:          6 :         case OBJ_POLY    : rName=ImpGetResStr(STR_ObjNamePluralPOLY    ); break;
    1998         [ +  - ]:          6 :         case OBJ_PATHLINE: rName=ImpGetResStr(STR_ObjNamePluralPATHLINE); break;
    1999         [ #  # ]:          0 :         case OBJ_FREELINE: rName=ImpGetResStr(STR_ObjNamePluralFREELINE); break;
    2000         [ #  # ]:          0 :         case OBJ_SPLNLINE: rName=ImpGetResStr(STR_ObjNamePluralNATSPLN); break;
    2001         [ +  - ]:         40 :         case OBJ_PATHFILL: rName=ImpGetResStr(STR_ObjNamePluralPATHFILL); break;
    2002         [ #  # ]:          0 :         case OBJ_FREEFILL: rName=ImpGetResStr(STR_ObjNamePluralFREEFILL); break;
    2003         [ #  # ]:          0 :         case OBJ_SPLNFILL: rName=ImpGetResStr(STR_ObjNamePluralPERSPLN); break;
    2004                 :          0 :         default: break;
    2005                 :            :     }
    2006                 :         64 : }
    2007                 :            : 
    2008                 :          0 : basegfx::B2DPolyPolygon SdrPathObj::TakeXorPoly() const
    2009                 :            : {
    2010                 :          0 :     return GetPathPoly();
    2011                 :            : }
    2012                 :            : 
    2013                 :          0 : sal_uInt32 SdrPathObj::GetHdlCount() const
    2014                 :            : {
    2015                 :          0 :     sal_uInt32 nRetval(0L);
    2016                 :          0 :     const sal_uInt32 nPolyCount(GetPathPoly().count());
    2017                 :            : 
    2018         [ #  # ]:          0 :     for(sal_uInt32 a(0L); a < nPolyCount; a++)
    2019                 :            :     {
    2020         [ #  # ]:          0 :         nRetval += GetPathPoly().getB2DPolygon(a).count();
    2021                 :            :     }
    2022                 :            : 
    2023                 :          0 :     return nRetval;
    2024                 :            : }
    2025                 :            : 
    2026                 :          0 : SdrHdl* SdrPathObj::GetHdl(sal_uInt32 nHdlNum) const
    2027                 :            : {
    2028                 :            :     // #i73248#
    2029                 :            :     // Warn the user that this is ineffective and show alternatives. Should not be used at all.
    2030                 :            :     OSL_FAIL("SdrPathObj::GetHdl(): ineffective, use AddToHdlList instead (!)");
    2031                 :            : 
    2032                 :            :     // to have an alternative, get single handle using the ineffective way
    2033                 :          0 :     SdrHdl* pRetval = 0;
    2034         [ #  # ]:          0 :     SdrHdlList aLocalList(0);
    2035         [ #  # ]:          0 :     AddToHdlList(aLocalList);
    2036                 :          0 :     const sal_uInt32 nHdlCount(aLocalList.GetHdlCount());
    2037                 :            : 
    2038 [ #  # ][ #  # ]:          0 :     if(nHdlCount && nHdlNum < nHdlCount)
    2039                 :            :     {
    2040                 :            :         // remove and remember. The other created handles will be deleted again with the
    2041                 :            :         // destruction of the local list
    2042         [ #  # ]:          0 :         pRetval = aLocalList.RemoveHdl(nHdlNum);
    2043                 :            :     }
    2044                 :            : 
    2045         [ #  # ]:          0 :     return pRetval;
    2046                 :            : }
    2047                 :            : 
    2048                 :        144 : void SdrPathObj::AddToHdlList(SdrHdlList& rHdlList) const
    2049                 :            : {
    2050                 :            :     // keep old stuff to be able to keep old SdrHdl stuff, too
    2051         [ +  - ]:        144 :     const XPolyPolygon aOldPathPolygon(GetPathPoly());
    2052         [ +  - ]:        144 :     sal_uInt16 nPolyCnt=aOldPathPolygon.Count();
    2053                 :        144 :     bool bClosed=IsClosed();
    2054                 :        144 :     sal_uInt16 nIdx=0;
    2055                 :            : 
    2056         [ +  + ]:        316 :     for (sal_uInt16 i=0; i<nPolyCnt; i++) {
    2057         [ +  - ]:        172 :         const XPolygon& rXPoly=aOldPathPolygon.GetObject(i);
    2058         [ +  - ]:        172 :         sal_uInt16 nPntCnt=rXPoly.GetPointCount();
    2059 [ +  + ][ +  - ]:        172 :         if (bClosed && nPntCnt>1) nPntCnt--;
    2060                 :            : 
    2061         [ +  + ]:       2582 :         for (sal_uInt16 j=0; j<nPntCnt; j++) {
    2062 [ +  - ][ +  + ]:       2410 :             if (rXPoly.GetFlags(j)!=XPOLY_CONTROL) {
    2063         [ +  - ]:       1022 :                 const Point& rPnt=rXPoly[j];
    2064 [ +  - ][ +  - ]:       1022 :                 SdrHdl* pHdl=new SdrHdl(rPnt,HDL_POLY);
    2065                 :       1022 :                 pHdl->SetPolyNum(i);
    2066                 :       1022 :                 pHdl->SetPointNum(j);
    2067         [ +  - ]:       1022 :                 pHdl->Set1PixMore(j==0);
    2068                 :       1022 :                 pHdl->SetSourceHdlNum(nIdx);
    2069                 :       1022 :                 nIdx++;
    2070         [ +  - ]:       1022 :                 rHdlList.AddHdl(pHdl);
    2071                 :            :             }
    2072                 :            :         }
    2073         [ +  - ]:        144 :     }
    2074                 :        144 : }
    2075                 :            : 
    2076                 :          0 : sal_uInt32 SdrPathObj::GetPlusHdlCount(const SdrHdl& rHdl) const
    2077                 :            : {
    2078                 :            :     // keep old stuff to be able to keep old SdrHdl stuff, too
    2079         [ #  # ]:          0 :     const XPolyPolygon aOldPathPolygon(GetPathPoly());
    2080                 :          0 :     sal_uInt16 nCnt = 0;
    2081                 :          0 :     sal_uInt16 nPnt = (sal_uInt16)rHdl.GetPointNum();
    2082                 :          0 :     sal_uInt16 nPolyNum = (sal_uInt16)rHdl.GetPolyNum();
    2083                 :            : 
    2084 [ #  # ][ #  # ]:          0 :     if(nPolyNum < aOldPathPolygon.Count())
    2085                 :            :     {
    2086         [ #  # ]:          0 :         const XPolygon& rXPoly = aOldPathPolygon[nPolyNum];
    2087         [ #  # ]:          0 :         sal_uInt16 nPntMax = rXPoly.GetPointCount();
    2088         [ #  # ]:          0 :         if (nPntMax>0)
    2089                 :            :         {
    2090                 :          0 :             nPntMax--;
    2091         [ #  # ]:          0 :             if (nPnt<=nPntMax)
    2092                 :            :             {
    2093 [ #  # ][ #  # ]:          0 :                 if (rXPoly.GetFlags(nPnt)!=XPOLY_CONTROL)
    2094                 :            :                 {
    2095 [ #  # ][ #  # ]:          0 :                     if (nPnt==0 && IsClosed()) nPnt=nPntMax;
                 [ #  # ]
    2096 [ #  # ][ #  # ]:          0 :                     if (nPnt>0 && rXPoly.GetFlags(nPnt-1)==XPOLY_CONTROL) nCnt++;
         [ #  # ][ #  # ]
    2097 [ #  # ][ #  # ]:          0 :                     if (nPnt==nPntMax && IsClosed()) nPnt=0;
                 [ #  # ]
    2098 [ #  # ][ #  # ]:          0 :                     if (nPnt<nPntMax && rXPoly.GetFlags(nPnt+1)==XPOLY_CONTROL) nCnt++;
         [ #  # ][ #  # ]
    2099                 :            :                 }
    2100                 :            :             }
    2101                 :            :         }
    2102                 :            :     }
    2103                 :            : 
    2104         [ #  # ]:          0 :     return nCnt;
    2105                 :            : }
    2106                 :            : 
    2107                 :          0 : SdrHdl* SdrPathObj::GetPlusHdl(const SdrHdl& rHdl, sal_uInt32 nPlusNum) const
    2108                 :            : {
    2109                 :            :     // keep old stuff to be able to keep old SdrHdl stuff, too
    2110         [ #  # ]:          0 :     const XPolyPolygon aOldPathPolygon(GetPathPoly());
    2111                 :          0 :     SdrHdl* pHdl = 0L;
    2112                 :          0 :     sal_uInt16 nPnt = (sal_uInt16)rHdl.GetPointNum();
    2113                 :          0 :     sal_uInt16 nPolyNum = (sal_uInt16)rHdl.GetPolyNum();
    2114                 :            : 
    2115 [ #  # ][ #  # ]:          0 :     if (nPolyNum<aOldPathPolygon.Count())
    2116                 :            :     {
    2117         [ #  # ]:          0 :         const XPolygon& rXPoly = aOldPathPolygon[nPolyNum];
    2118         [ #  # ]:          0 :         sal_uInt16 nPntMax = rXPoly.GetPointCount();
    2119                 :            : 
    2120         [ #  # ]:          0 :         if (nPntMax>0)
    2121                 :            :         {
    2122                 :          0 :             nPntMax--;
    2123         [ #  # ]:          0 :             if (nPnt<=nPntMax)
    2124                 :            :             {
    2125 [ #  # ][ #  # ]:          0 :                 pHdl=new SdrHdlBezWgt(&rHdl);
    2126                 :          0 :                 pHdl->SetPolyNum(rHdl.GetPolyNum());
    2127                 :            : 
    2128 [ #  # ][ #  # ]:          0 :                 if (nPnt==0 && IsClosed()) nPnt=nPntMax;
                 [ #  # ]
    2129 [ #  # ][ #  # ]:          0 :                 if (nPnt>0 && rXPoly.GetFlags(nPnt-1)==XPOLY_CONTROL && nPlusNum==0)
         [ #  # ][ #  # ]
                 [ #  # ]
    2130                 :            :                 {
    2131 [ #  # ][ #  # ]:          0 :                     pHdl->SetPos(rXPoly[nPnt-1]);
    2132                 :          0 :                     pHdl->SetPointNum(nPnt-1);
    2133                 :            :                 }
    2134                 :            :                 else
    2135                 :            :                 {
    2136 [ #  # ][ #  # ]:          0 :                     if (nPnt==nPntMax && IsClosed()) nPnt=0;
                 [ #  # ]
    2137 [ #  # ][ #  # ]:          0 :                     if (nPnt<rXPoly.GetPointCount()-1 && rXPoly.GetFlags(nPnt+1)==XPOLY_CONTROL)
         [ #  # ][ #  # ]
                 [ #  # ]
    2138                 :            :                     {
    2139 [ #  # ][ #  # ]:          0 :                         pHdl->SetPos(rXPoly[nPnt+1]);
    2140                 :          0 :                         pHdl->SetPointNum(nPnt+1);
    2141                 :            :                     }
    2142                 :            :                 }
    2143                 :            : 
    2144                 :          0 :                 pHdl->SetSourceHdlNum(rHdl.GetSourceHdlNum());
    2145                 :          0 :                 pHdl->SetPlusHdl(sal_True);
    2146                 :            :             }
    2147                 :            :         }
    2148                 :            :     }
    2149         [ #  # ]:          0 :     return pHdl;
    2150                 :            : }
    2151                 :            : 
    2152                 :            : ////////////////////////////////////////////////////////////////////////////////////////////////////
    2153                 :            : 
    2154                 :        151 : bool SdrPathObj::hasSpecialDrag() const
    2155                 :            : {
    2156                 :        151 :     return true;
    2157                 :            : }
    2158                 :            : 
    2159                 :          0 : bool SdrPathObj::beginSpecialDrag(SdrDragStat& rDrag) const
    2160                 :            : {
    2161         [ #  # ]:          0 :     ImpPathForDragAndCreate aDragAndCreate(*((SdrPathObj*)this));
    2162                 :            : 
    2163 [ #  # ][ #  # ]:          0 :     return aDragAndCreate.beginPathDrag(rDrag);
    2164                 :            : }
    2165                 :            : 
    2166                 :          0 : bool SdrPathObj::applySpecialDrag(SdrDragStat& rDrag)
    2167                 :            : {
    2168         [ #  # ]:          0 :     ImpPathForDragAndCreate aDragAndCreate(*this);
    2169         [ #  # ]:          0 :     bool bRetval(aDragAndCreate.beginPathDrag(rDrag));
    2170                 :            : 
    2171         [ #  # ]:          0 :     if(bRetval)
    2172                 :            :     {
    2173         [ #  # ]:          0 :         bRetval = aDragAndCreate.movePathDrag(rDrag);
    2174                 :            :     }
    2175                 :            : 
    2176         [ #  # ]:          0 :     if(bRetval)
    2177                 :            :     {
    2178         [ #  # ]:          0 :         bRetval = aDragAndCreate.endPathDrag(rDrag);
    2179                 :            :     }
    2180                 :            : 
    2181         [ #  # ]:          0 :     if(bRetval)
    2182                 :            :     {
    2183 [ #  # ][ #  # ]:          0 :            NbcSetPathPoly(aDragAndCreate.getModifiedPolyPolygon());
                 [ #  # ]
    2184                 :            :     }
    2185                 :            : 
    2186         [ #  # ]:          0 :     return bRetval;
    2187                 :            : }
    2188                 :            : 
    2189                 :          0 : String SdrPathObj::getSpecialDragComment(const SdrDragStat& rDrag) const
    2190                 :            : {
    2191                 :          0 :     String aRetval;
    2192                 :            : 
    2193         [ #  # ]:          0 :     if(mpDAC)
    2194                 :            :     {
    2195                 :            :         // #i103058# also get a comment when in creation
    2196 [ #  # ][ #  # ]:          0 :         const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj());
    2197                 :            : 
    2198         [ #  # ]:          0 :         if(bCreateComment)
    2199                 :            :         {
    2200 [ #  # ][ #  # ]:          0 :             aRetval = mpDAC->getSpecialDragComment(rDrag);
                 [ #  # ]
    2201                 :            :         }
    2202                 :            :     }
    2203                 :            :     else
    2204                 :            :     {
    2205         [ #  # ]:          0 :         ImpPathForDragAndCreate aDragAndCreate(*((SdrPathObj*)this));
    2206         [ #  # ]:          0 :         bool bDidWork(aDragAndCreate.beginPathDrag((SdrDragStat&)rDrag));
    2207                 :            : 
    2208         [ #  # ]:          0 :         if(bDidWork)
    2209                 :            :         {
    2210 [ #  # ][ #  # ]:          0 :             aRetval = aDragAndCreate.getSpecialDragComment(rDrag);
                 [ #  # ]
    2211         [ #  # ]:          0 :         }
    2212                 :            :     }
    2213                 :            : 
    2214                 :          0 :     return aRetval;
    2215                 :            : }
    2216                 :            : 
    2217                 :          0 : basegfx::B2DPolyPolygon SdrPathObj::getSpecialDragPoly(const SdrDragStat& rDrag) const
    2218                 :            : {
    2219         [ #  # ]:          0 :     basegfx::B2DPolyPolygon aRetval;
    2220         [ #  # ]:          0 :     ImpPathForDragAndCreate aDragAndCreate(*((SdrPathObj*)this));
    2221         [ #  # ]:          0 :     bool bDidWork(aDragAndCreate.beginPathDrag((SdrDragStat&)rDrag));
    2222                 :            : 
    2223         [ #  # ]:          0 :     if(bDidWork)
    2224                 :            :     {
    2225 [ #  # ][ #  # ]:          0 :         aRetval = aDragAndCreate.getSpecialDragPoly(rDrag);
                 [ #  # ]
    2226                 :            :     }
    2227                 :            : 
    2228         [ #  # ]:          0 :     return aRetval;
    2229                 :            : }
    2230                 :            : 
    2231                 :            : ////////////////////////////////////////////////////////////////////////////////////////////////////
    2232                 :            : 
    2233                 :          0 : bool SdrPathObj::BegCreate(SdrDragStat& rStat)
    2234                 :            : {
    2235                 :          0 :     impDeleteDAC();
    2236                 :          0 :     return impGetDAC().BegCreate(rStat);
    2237                 :            : }
    2238                 :            : 
    2239                 :          0 : bool SdrPathObj::MovCreate(SdrDragStat& rStat)
    2240                 :            : {
    2241                 :          0 :     return impGetDAC().MovCreate(rStat);
    2242                 :            : }
    2243                 :            : 
    2244                 :          0 : bool SdrPathObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
    2245                 :            : {
    2246                 :          0 :     bool bRetval(impGetDAC().EndCreate(rStat, eCmd));
    2247                 :            : 
    2248 [ #  # ][ #  # ]:          0 :     if(bRetval && mpDAC)
    2249                 :            :     {
    2250         [ #  # ]:          0 :         SetPathPoly(mpDAC->getModifiedPolyPolygon());
    2251                 :            : 
    2252                 :            :         // #i75974# Check for AutoClose feature. Moved here from ImpPathForDragAndCreate::EndCreate
    2253                 :            :         // to be able to use the type-changing ImpSetClosed method
    2254         [ #  # ]:          0 :         if(!IsClosedObj())
    2255                 :            :         {
    2256                 :          0 :             SdrView* pView = rStat.GetView();
    2257                 :            : 
    2258 [ #  # ][ #  # ]:          0 :             if(pView && pView->IsAutoClosePolys() && !pView->IsUseIncompatiblePathCreateInterface())
         [ #  # ][ #  # ]
    2259                 :            :             {
    2260                 :          0 :                 OutputDevice* pOut = pView->GetFirstOutputDevice();
    2261                 :            : 
    2262         [ #  # ]:          0 :                 if(pOut)
    2263                 :            :                 {
    2264         [ #  # ]:          0 :                     if(GetPathPoly().count())
    2265                 :            :                     {
    2266         [ #  # ]:          0 :                         const basegfx::B2DPolygon aCandidate(GetPathPoly().getB2DPolygon(0));
    2267                 :            : 
    2268 [ #  # ][ #  # ]:          0 :                         if(aCandidate.count() > 2)
    2269                 :            :                         {
    2270                 :            :                             // check distance of first and last point
    2271         [ #  # ]:          0 :                             const sal_Int32 nCloseDist(pOut->PixelToLogic(Size(pView->GetAutoCloseDistPix(), 0)).Width());
    2272 [ #  # ][ #  # ]:          0 :                             const basegfx::B2DVector aDistVector(aCandidate.getB2DPoint(aCandidate.count() - 1) - aCandidate.getB2DPoint(0));
                 [ #  # ]
    2273                 :            : 
    2274 [ #  # ][ #  # ]:          0 :                             if(aDistVector.getLength() <= (double)nCloseDist)
    2275                 :            :                             {
    2276                 :            :                                 // close it
    2277         [ #  # ]:          0 :                                 ImpSetClosed(true);
    2278                 :          0 :                             }
    2279         [ #  # ]:          0 :                         }
    2280                 :            :                     }
    2281                 :            :                 }
    2282                 :            :             }
    2283                 :            :         }
    2284                 :            : 
    2285                 :          0 :         impDeleteDAC();
    2286                 :            :     }
    2287                 :            : 
    2288                 :          0 :     return bRetval;
    2289                 :            : }
    2290                 :            : 
    2291                 :          0 : bool SdrPathObj::BckCreate(SdrDragStat& rStat)
    2292                 :            : {
    2293                 :          0 :     return impGetDAC().BckCreate(rStat);
    2294                 :            : }
    2295                 :            : 
    2296                 :          0 : void SdrPathObj::BrkCreate(SdrDragStat& rStat)
    2297                 :            : {
    2298                 :          0 :     impGetDAC().BrkCreate(rStat);
    2299                 :          0 :     impDeleteDAC();
    2300                 :          0 : }
    2301                 :            : 
    2302                 :          0 : basegfx::B2DPolyPolygon SdrPathObj::TakeCreatePoly(const SdrDragStat& rDrag) const
    2303                 :            : {
    2304                 :          0 :     basegfx::B2DPolyPolygon aRetval;
    2305                 :            : 
    2306         [ #  # ]:          0 :     if(mpDAC)
    2307                 :            :     {
    2308 [ #  # ][ #  # ]:          0 :         aRetval = mpDAC->TakeObjectPolyPolygon(rDrag);
                 [ #  # ]
    2309 [ #  # ][ #  # ]:          0 :         aRetval.append(mpDAC->TakeDragPolyPolygon(rDrag));
                 [ #  # ]
    2310                 :            :     }
    2311                 :            : 
    2312                 :          0 :     return aRetval;
    2313                 :            : }
    2314                 :            : 
    2315                 :            : // during drag or create, allow accessing the so-far created/modified polyPolygon
    2316                 :          0 : basegfx::B2DPolyPolygon SdrPathObj::getObjectPolyPolygon(const SdrDragStat& rDrag) const
    2317                 :            : {
    2318                 :          0 :     basegfx::B2DPolyPolygon aRetval;
    2319                 :            : 
    2320         [ #  # ]:          0 :     if(mpDAC)
    2321                 :            :     {
    2322 [ #  # ][ #  # ]:          0 :         aRetval = mpDAC->TakeObjectPolyPolygon(rDrag);
                 [ #  # ]
    2323                 :            :     }
    2324                 :            : 
    2325                 :          0 :     return aRetval;
    2326                 :            : }
    2327                 :            : 
    2328                 :          0 : basegfx::B2DPolyPolygon SdrPathObj::getDragPolyPolygon(const SdrDragStat& rDrag) const
    2329                 :            : {
    2330                 :          0 :     basegfx::B2DPolyPolygon aRetval;
    2331                 :            : 
    2332         [ #  # ]:          0 :     if(mpDAC)
    2333                 :            :     {
    2334 [ #  # ][ #  # ]:          0 :         aRetval = mpDAC->TakeDragPolyPolygon(rDrag);
                 [ #  # ]
    2335                 :            :     }
    2336                 :            : 
    2337                 :          0 :     return aRetval;
    2338                 :            : }
    2339                 :            : 
    2340                 :          0 : Pointer SdrPathObj::GetCreatePointer() const
    2341                 :            : {
    2342                 :          0 :     return impGetDAC().GetCreatePointer();
    2343                 :            : }
    2344                 :            : 
    2345                 :      37073 : void SdrPathObj::NbcMove(const Size& rSiz)
    2346                 :            : {
    2347         [ +  - ]:      37073 :     maPathPolygon.transform(basegfx::tools::createTranslateB2DHomMatrix(rSiz.Width(), rSiz.Height()));
    2348                 :            : 
    2349                 :            :     // #i19871# first modify locally, then call parent (to get correct SnapRect with GluePoints)
    2350                 :      37073 :     SdrTextObj::NbcMove(rSiz);
    2351                 :      37073 : }
    2352                 :            : 
    2353                 :      35820 : void SdrPathObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
    2354                 :            : {
    2355         [ +  - ]:      35820 :     basegfx::B2DHomMatrix aTrans(basegfx::tools::createTranslateB2DHomMatrix(-rRef.X(), -rRef.Y()));
    2356                 :            :     aTrans = basegfx::tools::createScaleTranslateB2DHomMatrix(
    2357 [ +  - ][ +  - ]:      35820 :         double(xFact), double(yFact), rRef.X(), rRef.Y()) * aTrans;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2358         [ +  - ]:      35820 :     maPathPolygon.transform(aTrans);
    2359                 :            : 
    2360                 :            :     // #i19871# first modify locally, then call parent (to get correct SnapRect with GluePoints)
    2361 [ +  - ][ +  - ]:      35820 :     SdrTextObj::NbcResize(rRef,xFact,yFact);
    2362                 :      35820 : }
    2363                 :            : 
    2364                 :          0 : void SdrPathObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
    2365                 :            : {
    2366                 :            :     // Thank JOE, the angles are defined mirrored to the mathematical meanings
    2367         [ #  # ]:          0 :     const basegfx::B2DHomMatrix aTrans(basegfx::tools::createRotateAroundPoint(rRef.X(), rRef.Y(), -nWink * nPi180));
    2368         [ #  # ]:          0 :     maPathPolygon.transform(aTrans);
    2369                 :            : 
    2370                 :            :     // #i19871# first modify locally, then call parent (to get correct SnapRect with GluePoints)
    2371 [ #  # ][ #  # ]:          0 :     SdrTextObj::NbcRotate(rRef,nWink,sn,cs);
    2372                 :          0 : }
    2373                 :            : 
    2374                 :          0 : void SdrPathObj::NbcShear(const Point& rRefPnt, long nAngle, double fTan, bool bVShear)
    2375                 :            : {
    2376         [ #  # ]:          0 :     basegfx::B2DHomMatrix aTrans(basegfx::tools::createTranslateB2DHomMatrix(-rRefPnt.X(), -rRefPnt.Y()));
    2377                 :            : 
    2378         [ #  # ]:          0 :     if(bVShear)
    2379                 :            :     {
    2380                 :            :         // Thank JOE, the angles are defined mirrored to the mathematical meanings
    2381         [ #  # ]:          0 :         aTrans.shearY(-fTan);
    2382                 :            :     }
    2383                 :            :     else
    2384                 :            :     {
    2385         [ #  # ]:          0 :         aTrans.shearX(-fTan);
    2386                 :            :     }
    2387                 :            : 
    2388         [ #  # ]:          0 :     aTrans.translate(rRefPnt.X(), rRefPnt.Y());
    2389         [ #  # ]:          0 :     maPathPolygon.transform(aTrans);
    2390                 :            : 
    2391                 :            :     // #i19871# first modify locally, then call parent (to get correct SnapRect with GluePoints)
    2392 [ #  # ][ #  # ]:          0 :     SdrTextObj::NbcShear(rRefPnt,nAngle,fTan,bVShear);
    2393                 :          0 : }
    2394                 :            : 
    2395                 :          0 : void SdrPathObj::NbcMirror(const Point& rRefPnt1, const Point& rRefPnt2)
    2396                 :            : {
    2397                 :          0 :     const double fDiffX(rRefPnt2.X() - rRefPnt1.X());
    2398                 :          0 :     const double fDiffY(rRefPnt2.Y() - rRefPnt1.Y());
    2399                 :          0 :     const double fRot(atan2(fDiffY, fDiffX));
    2400         [ #  # ]:          0 :     basegfx::B2DHomMatrix aTrans(basegfx::tools::createTranslateB2DHomMatrix(-rRefPnt1.X(), -rRefPnt1.Y()));
    2401         [ #  # ]:          0 :     aTrans.rotate(-fRot);
    2402         [ #  # ]:          0 :     aTrans.scale(1.0, -1.0);
    2403         [ #  # ]:          0 :     aTrans.rotate(fRot);
    2404         [ #  # ]:          0 :     aTrans.translate(rRefPnt1.X(), rRefPnt1.Y());
    2405         [ #  # ]:          0 :     maPathPolygon.transform(aTrans);
    2406                 :            : 
    2407                 :            :     // Do Joe's special handling for lines when mirroring, too
    2408         [ #  # ]:          0 :     ImpForceKind();
    2409                 :            : 
    2410                 :            :     // #i19871# first modify locally, then call parent (to get correct SnapRect with GluePoints)
    2411 [ #  # ][ #  # ]:          0 :     SdrTextObj::NbcMirror(rRefPnt1,rRefPnt2);
    2412                 :          0 : }
    2413                 :            : 
    2414                 :          0 : void SdrPathObj::TakeUnrotatedSnapRect(Rectangle& rRect) const
    2415                 :            : {
    2416         [ #  # ]:          0 :     if(!aGeo.nDrehWink)
    2417                 :            :     {
    2418                 :          0 :         rRect = GetSnapRect();
    2419                 :            :     }
    2420                 :            :     else
    2421                 :            :     {
    2422         [ #  # ]:          0 :         XPolyPolygon aXPP(GetPathPoly());
    2423         [ #  # ]:          0 :         RotateXPoly(aXPP,Point(),-aGeo.nSin,aGeo.nCos);
    2424         [ #  # ]:          0 :         rRect=aXPP.GetBoundRect();
    2425                 :          0 :         Point aTmp(rRect.TopLeft());
    2426                 :          0 :         RotatePoint(aTmp,Point(),aGeo.nSin,aGeo.nCos);
    2427                 :          0 :         aTmp-=rRect.TopLeft();
    2428 [ #  # ][ #  # ]:          0 :         rRect.Move(aTmp.X(),aTmp.Y());
    2429                 :            :     }
    2430                 :          0 : }
    2431                 :            : 
    2432                 :      49924 : void SdrPathObj::RecalcSnapRect()
    2433                 :            : {
    2434         [ +  + ]:      49924 :     if(GetPathPoly().count())
    2435                 :            :     {
    2436                 :      15358 :         maSnapRect = ImpGetBoundRect(GetPathPoly());
    2437                 :            :     }
    2438                 :      49924 : }
    2439                 :            : 
    2440                 :      35809 : void SdrPathObj::NbcSetSnapRect(const Rectangle& rRect)
    2441                 :            : {
    2442         [ +  - ]:      35809 :     Rectangle aOld(GetSnapRect());
    2443                 :            : 
    2444                 :            :     // Take RECT_EMPTY into account when calculating scale factors
    2445         [ +  + ]:      35809 :     long nMulX = (RECT_EMPTY == rRect.Right()) ? 0 : rRect.Right()  - rRect.Left();
    2446                 :            : 
    2447                 :      35809 :     long nDivX = aOld.Right()   - aOld.Left();
    2448                 :            : 
    2449                 :            :     // Take RECT_EMPTY into account when calculating scale factors
    2450         [ +  + ]:      35809 :     long nMulY = (RECT_EMPTY == rRect.Bottom()) ? 0 : rRect.Bottom() - rRect.Top();
    2451                 :            : 
    2452                 :      35809 :     long nDivY = aOld.Bottom()  - aOld.Top();
    2453         [ -  + ]:      35809 :     if ( nDivX == 0 ) { nMulX = 1; nDivX = 1; }
    2454         [ -  + ]:      35809 :     if ( nDivY == 0 ) { nMulY = 1; nDivY = 1; }
    2455         [ +  - ]:      35809 :     Fraction aX(nMulX,nDivX);
    2456         [ +  - ]:      35809 :     Fraction aY(nMulY,nDivY);
    2457         [ +  - ]:      35809 :     NbcResize(aOld.TopLeft(), aX, aY);
    2458         [ +  - ]:      35809 :     NbcMove(Size(rRect.Left() - aOld.Left(), rRect.Top() - aOld.Top()));
    2459                 :      35809 : }
    2460                 :            : 
    2461                 :          0 : sal_uInt32 SdrPathObj::GetSnapPointCount() const
    2462                 :            : {
    2463                 :          0 :     return GetHdlCount();
    2464                 :            : }
    2465                 :            : 
    2466                 :          0 : Point SdrPathObj::GetSnapPoint(sal_uInt32 nSnapPnt) const
    2467                 :            : {
    2468                 :            :     sal_uInt32 nPoly,nPnt;
    2469         [ #  # ]:          0 :     if(!PolyPolygonEditor::GetRelativePolyPoint(GetPathPoly(), nSnapPnt, nPoly, nPnt))
    2470                 :            :     {
    2471                 :            :         DBG_ASSERT(sal_False,"SdrPathObj::GetSnapPoint: Point nSnapPnt does not exist.");
    2472                 :            :     }
    2473                 :            : 
    2474 [ #  # ][ #  # ]:          0 :     const basegfx::B2DPoint aB2DPoint(GetPathPoly().getB2DPolygon(nPoly).getB2DPoint(nPnt));
                 [ #  # ]
    2475                 :          0 :     return Point(FRound(aB2DPoint.getX()), FRound(aB2DPoint.getY()));
    2476                 :            : }
    2477                 :            : 
    2478                 :        150 : sal_Bool SdrPathObj::IsPolyObj() const
    2479                 :            : {
    2480                 :        150 :     return sal_True;
    2481                 :            : }
    2482                 :            : 
    2483                 :          3 : sal_uInt32 SdrPathObj::GetPointCount() const
    2484                 :            : {
    2485                 :          3 :     const sal_uInt32 nPolyCount(GetPathPoly().count());
    2486                 :          3 :     sal_uInt32 nRetval(0L);
    2487                 :            : 
    2488         [ +  + ]:          6 :     for(sal_uInt32 a(0L); a < nPolyCount; a++)
    2489                 :            :     {
    2490         [ +  - ]:          3 :         nRetval += GetPathPoly().getB2DPolygon(a).count();
    2491                 :            :     }
    2492                 :            : 
    2493                 :          3 :     return nRetval;
    2494                 :            : }
    2495                 :            : 
    2496                 :          6 : Point SdrPathObj::GetPoint(sal_uInt32 nHdlNum) const
    2497                 :            : {
    2498                 :          6 :     Point aRetval;
    2499                 :            :     sal_uInt32 nPoly,nPnt;
    2500                 :            : 
    2501 [ +  - ][ +  - ]:          6 :     if(PolyPolygonEditor::GetRelativePolyPoint(GetPathPoly(), nHdlNum, nPoly, nPnt))
    2502                 :            :     {
    2503         [ +  - ]:          6 :         const basegfx::B2DPolygon aPoly(GetPathPoly().getB2DPolygon(nPoly));
    2504         [ +  - ]:          6 :         const basegfx::B2DPoint aPoint(aPoly.getB2DPoint(nPnt));
    2505         [ +  - ]:          6 :         aRetval = Point(FRound(aPoint.getX()), FRound(aPoint.getY()));
    2506                 :            :     }
    2507                 :            : 
    2508                 :          6 :     return aRetval;
    2509                 :            : }
    2510                 :            : 
    2511                 :          0 : void SdrPathObj::NbcSetPoint(const Point& rPnt, sal_uInt32 nHdlNum)
    2512                 :            : {
    2513                 :            :     sal_uInt32 nPoly,nPnt;
    2514                 :            : 
    2515 [ #  # ][ #  # ]:          0 :     if(PolyPolygonEditor::GetRelativePolyPoint(GetPathPoly(), nHdlNum, nPoly, nPnt))
    2516                 :            :     {
    2517         [ #  # ]:          0 :         basegfx::B2DPolygon aNewPolygon(GetPathPoly().getB2DPolygon(nPoly));
    2518         [ #  # ]:          0 :         aNewPolygon.setB2DPoint(nPnt, basegfx::B2DPoint(rPnt.X(), rPnt.Y()));
    2519         [ #  # ]:          0 :         maPathPolygon.setB2DPolygon(nPoly, aNewPolygon);
    2520                 :            : 
    2521         [ #  # ]:          0 :         if(meKind==OBJ_LINE)
    2522                 :            :         {
    2523         [ #  # ]:          0 :             ImpForceLineWink();
    2524                 :            :         }
    2525                 :            :         else
    2526                 :            :         {
    2527 [ #  # ][ #  # ]:          0 :             if(GetPathPoly().count())
    2528                 :            :             {
    2529                 :            :                 // #i10659# for SdrTextObj, keep aRect up to date
    2530         [ #  # ]:          0 :                 aRect = ImpGetBoundRect(GetPathPoly());
    2531                 :            :             }
    2532                 :            :         }
    2533                 :            : 
    2534 [ #  # ][ #  # ]:          0 :         SetRectsDirty();
    2535                 :            :     }
    2536                 :          0 : }
    2537                 :            : 
    2538                 :          0 : sal_uInt32 SdrPathObj::NbcInsPointOld(const Point& rPos, sal_Bool bNewObj, sal_Bool bHideHim)
    2539                 :            : {
    2540                 :            :     sal_uInt32 nNewHdl;
    2541                 :            : 
    2542         [ #  # ]:          0 :     if(bNewObj)
    2543                 :            :     {
    2544                 :          0 :         nNewHdl = NbcInsPoint(0L, rPos, sal_True, bHideHim);
    2545                 :            :     }
    2546                 :            :     else
    2547                 :            :     {
    2548                 :            :         // look for smallest distance data
    2549                 :          0 :         const basegfx::B2DPoint aTestPoint(rPos.X(), rPos.Y());
    2550                 :          0 :         sal_uInt32 nSmallestPolyIndex(0L);
    2551                 :          0 :         sal_uInt32 nSmallestEdgeIndex(0L);
    2552                 :            :         double fSmallestCut;
    2553         [ #  # ]:          0 :         basegfx::tools::getSmallestDistancePointToPolyPolygon(GetPathPoly(), aTestPoint, nSmallestPolyIndex, nSmallestEdgeIndex, fSmallestCut);
    2554                 :            : 
    2555                 :            :         // create old polygon index from it
    2556                 :          0 :         sal_uInt32 nPolyIndex(nSmallestEdgeIndex);
    2557                 :            : 
    2558         [ #  # ]:          0 :         for(sal_uInt32 a(0L); a < nSmallestPolyIndex; a++)
    2559                 :            :         {
    2560 [ #  # ][ #  # ]:          0 :             nPolyIndex += GetPathPoly().getB2DPolygon(a).count();
                 [ #  # ]
    2561                 :            :         }
    2562                 :            : 
    2563         [ #  # ]:          0 :         nNewHdl = NbcInsPoint(nPolyIndex, rPos, sal_False, bHideHim);
    2564                 :            :     }
    2565                 :            : 
    2566                 :          0 :     ImpForceKind();
    2567                 :          0 :     return nNewHdl;
    2568                 :            : }
    2569                 :            : 
    2570                 :          0 : sal_uInt32 SdrPathObj::NbcInsPoint(sal_uInt32 /*nHdlNum*/, const Point& rPos, sal_Bool bNewObj, sal_Bool /*bHideHim*/)
    2571                 :            : {
    2572                 :            :     sal_uInt32 nNewHdl;
    2573                 :            : 
    2574         [ #  # ]:          0 :     if(bNewObj)
    2575                 :            :     {
    2576         [ #  # ]:          0 :         basegfx::B2DPolygon aNewPoly;
    2577                 :          0 :         const basegfx::B2DPoint aPoint(rPos.X(), rPos.Y());
    2578         [ #  # ]:          0 :         aNewPoly.append(aPoint);
    2579         [ #  # ]:          0 :         aNewPoly.setClosed(IsClosed());
    2580         [ #  # ]:          0 :         maPathPolygon.append(aNewPoly);
    2581         [ #  # ]:          0 :         SetRectsDirty();
    2582 [ #  # ][ #  # ]:          0 :         nNewHdl = GetHdlCount();
    2583                 :            :     }
    2584                 :            :     else
    2585                 :            :     {
    2586                 :            :         // look for smallest distance data
    2587                 :          0 :         const basegfx::B2DPoint aTestPoint(rPos.X(), rPos.Y());
    2588                 :          0 :         sal_uInt32 nSmallestPolyIndex(0L);
    2589                 :          0 :         sal_uInt32 nSmallestEdgeIndex(0L);
    2590                 :            :         double fSmallestCut;
    2591         [ #  # ]:          0 :         basegfx::tools::getSmallestDistancePointToPolyPolygon(GetPathPoly(), aTestPoint, nSmallestPolyIndex, nSmallestEdgeIndex, fSmallestCut);
    2592         [ #  # ]:          0 :         basegfx::B2DPolygon aCandidate(GetPathPoly().getB2DPolygon(nSmallestPolyIndex));
    2593 [ #  # ][ #  # ]:          0 :         const bool bBefore(!aCandidate.isClosed() && 0L == nSmallestEdgeIndex && 0.0 == fSmallestCut);
         [ #  # ][ #  # ]
    2594 [ #  # ][ #  # ]:          0 :         const bool bAfter(!aCandidate.isClosed() && aCandidate.count() == nSmallestEdgeIndex + 2L && 1.0 == fSmallestCut);
         [ #  # ][ #  # ]
                 [ #  # ]
    2595                 :            : 
    2596         [ #  # ]:          0 :         if(bBefore)
    2597                 :            :         {
    2598                 :            :             // before first point
    2599         [ #  # ]:          0 :             aCandidate.insert(0L, aTestPoint);
    2600                 :            : 
    2601 [ #  # ][ #  # ]:          0 :             if(aCandidate.areControlPointsUsed())
    2602                 :            :             {
    2603 [ #  # ][ #  # ]:          0 :                 if(aCandidate.isNextControlPointUsed(1))
    2604                 :            :                 {
    2605 [ #  # ][ #  # ]:          0 :                     aCandidate.setNextControlPoint(0, interpolate(aTestPoint, aCandidate.getB2DPoint(1), (1.0 / 3.0)));
    2606 [ #  # ][ #  # ]:          0 :                     aCandidate.setPrevControlPoint(1, interpolate(aTestPoint, aCandidate.getB2DPoint(1), (2.0 / 3.0)));
    2607                 :            :                 }
    2608                 :            :             }
    2609                 :            : 
    2610                 :          0 :             nNewHdl = 0L;
    2611                 :            :         }
    2612         [ #  # ]:          0 :         else if(bAfter)
    2613                 :            :         {
    2614                 :            :             // after last point
    2615         [ #  # ]:          0 :             aCandidate.append(aTestPoint);
    2616                 :            : 
    2617 [ #  # ][ #  # ]:          0 :             if(aCandidate.areControlPointsUsed())
    2618                 :            :             {
    2619 [ #  # ][ #  # ]:          0 :                 if(aCandidate.isPrevControlPointUsed(aCandidate.count() - 2))
                 [ #  # ]
    2620                 :            :                 {
    2621 [ #  # ][ #  # ]:          0 :                     aCandidate.setNextControlPoint(aCandidate.count() - 2, interpolate(aCandidate.getB2DPoint(aCandidate.count() - 2), aTestPoint, (1.0 / 3.0)));
         [ #  # ][ #  # ]
    2622 [ #  # ][ #  # ]:          0 :                     aCandidate.setPrevControlPoint(aCandidate.count() - 1, interpolate(aCandidate.getB2DPoint(aCandidate.count() - 2), aTestPoint, (2.0 / 3.0)));
         [ #  # ][ #  # ]
    2623                 :            :                 }
    2624                 :            :             }
    2625                 :            : 
    2626         [ #  # ]:          0 :             nNewHdl = aCandidate.count() - 1L;
    2627                 :            :         }
    2628                 :            :         else
    2629                 :            :         {
    2630                 :            :             // in between
    2631                 :          0 :             bool bSegmentSplit(false);
    2632         [ #  # ]:          0 :             const sal_uInt32 nNextIndex((nSmallestEdgeIndex + 1) % aCandidate.count());
    2633                 :            : 
    2634 [ #  # ][ #  # ]:          0 :             if(aCandidate.areControlPointsUsed())
    2635                 :            :             {
    2636 [ #  # ][ #  # ]:          0 :                 if(aCandidate.isNextControlPointUsed(nSmallestEdgeIndex) || aCandidate.isPrevControlPointUsed(nNextIndex))
         [ #  # ][ #  # ]
                 [ #  # ]
    2637                 :            :                 {
    2638                 :          0 :                     bSegmentSplit = true;
    2639                 :            :                 }
    2640                 :            :             }
    2641                 :            : 
    2642         [ #  # ]:          0 :             if(bSegmentSplit)
    2643                 :            :             {
    2644                 :            :                 // rebuild original segment to get the split data
    2645 [ #  # ][ #  # ]:          0 :                 basegfx::B2DCubicBezier aBezierA, aBezierB;
    2646                 :            :                 const basegfx::B2DCubicBezier aBezier(
    2647                 :            :                     aCandidate.getB2DPoint(nSmallestEdgeIndex),
    2648                 :            :                     aCandidate.getNextControlPoint(nSmallestEdgeIndex),
    2649                 :            :                     aCandidate.getPrevControlPoint(nNextIndex),
    2650 [ #  # ][ #  # ]:          0 :                     aCandidate.getB2DPoint(nNextIndex));
         [ #  # ][ #  # ]
                 [ #  # ]
    2651                 :            : 
    2652                 :            :                 // split and insert hit point
    2653         [ #  # ]:          0 :                 aBezier.split(fSmallestCut, &aBezierA, &aBezierB);
    2654         [ #  # ]:          0 :                 aCandidate.insert(nSmallestEdgeIndex + 1, aTestPoint);
    2655                 :            : 
    2656                 :            :                 // since we inserted hit point and not split point, we need to add an offset
    2657                 :            :                 // to the control points to get the C1 continuity we want to achieve
    2658                 :          0 :                 const basegfx::B2DVector aOffset(aTestPoint - aBezierA.getEndPoint());
    2659         [ #  # ]:          0 :                 aCandidate.setNextControlPoint(nSmallestEdgeIndex, aBezierA.getControlPointA() + aOffset);
    2660         [ #  # ]:          0 :                 aCandidate.setPrevControlPoint(nSmallestEdgeIndex + 1, aBezierA.getControlPointB() + aOffset);
    2661         [ #  # ]:          0 :                 aCandidate.setNextControlPoint(nSmallestEdgeIndex + 1, aBezierB.getControlPointA() + aOffset);
    2662 [ #  # ][ #  # ]:          0 :                 aCandidate.setPrevControlPoint((nSmallestEdgeIndex + 2) % aCandidate.count(), aBezierB.getControlPointB() + aOffset);
         [ #  # ][ #  # ]
                 [ #  # ]
    2663                 :            :             }
    2664                 :            :             else
    2665                 :            :             {
    2666         [ #  # ]:          0 :                 aCandidate.insert(nSmallestEdgeIndex + 1L, aTestPoint);
    2667                 :            :             }
    2668                 :            : 
    2669                 :          0 :             nNewHdl = nSmallestEdgeIndex + 1L;
    2670                 :            :         }
    2671                 :            : 
    2672         [ #  # ]:          0 :         maPathPolygon.setB2DPolygon(nSmallestPolyIndex, aCandidate);
    2673                 :            : 
    2674                 :            :         // create old polygon index from it
    2675         [ #  # ]:          0 :         for(sal_uInt32 a(0L); a < nSmallestPolyIndex; a++)
    2676                 :            :         {
    2677 [ #  # ][ #  # ]:          0 :             nNewHdl += GetPathPoly().getB2DPolygon(a).count();
                 [ #  # ]
    2678         [ #  # ]:          0 :         }
    2679                 :            :     }
    2680                 :            : 
    2681                 :          0 :     ImpForceKind();
    2682                 :          0 :     return nNewHdl;
    2683                 :            : }
    2684                 :            : 
    2685                 :          0 : SdrObject* SdrPathObj::RipPoint(sal_uInt32 nHdlNum, sal_uInt32& rNewPt0Index)
    2686                 :            : {
    2687                 :          0 :     SdrPathObj* pNewObj = 0L;
    2688         [ #  # ]:          0 :     const basegfx::B2DPolyPolygon aLocalPolyPolygon(GetPathPoly());
    2689                 :            :     sal_uInt32 nPoly, nPnt;
    2690                 :            : 
    2691 [ #  # ][ #  # ]:          0 :     if(PolyPolygonEditor::GetRelativePolyPoint(aLocalPolyPolygon, nHdlNum, nPoly, nPnt))
    2692                 :            :     {
    2693         [ #  # ]:          0 :         if(0L == nPoly)
    2694                 :            :         {
    2695         [ #  # ]:          0 :             const basegfx::B2DPolygon aCandidate(aLocalPolyPolygon.getB2DPolygon(nPoly));
    2696         [ #  # ]:          0 :             const sal_uInt32 nPointCount(aCandidate.count());
    2697                 :            : 
    2698         [ #  # ]:          0 :             if(nPointCount)
    2699                 :            :             {
    2700         [ #  # ]:          0 :                 if(IsClosed())
    2701                 :            :                 {
    2702                 :            :                     // when closed, RipPoint means to open the polygon at the selected point. To
    2703                 :            :                     // be able to do that, it is necessary to make the selected point the first one
    2704         [ #  # ]:          0 :                     basegfx::B2DPolygon aNewPolygon(basegfx::tools::makeStartPoint(aCandidate, nPnt));
    2705 [ #  # ][ #  # ]:          0 :                     SetPathPoly(basegfx::B2DPolyPolygon(aNewPolygon));
                 [ #  # ]
    2706         [ #  # ]:          0 :                     ToggleClosed();
    2707                 :            : 
    2708                 :            :                     // give back new position of old start point (historical reasons)
    2709         [ #  # ]:          0 :                     rNewPt0Index = (nPointCount - nPnt) % nPointCount;
    2710                 :            :                 }
    2711                 :            :                 else
    2712                 :            :                 {
    2713 [ #  # ][ #  # ]:          0 :                     if(nPointCount >= 3L && nPnt != 0L && nPnt + 1L < nPointCount)
                 [ #  # ]
    2714                 :            :                     {
    2715                 :            :                         // split in two objects at point nPnt
    2716         [ #  # ]:          0 :                         basegfx::B2DPolygon aSplitPolyA(aCandidate, 0L, nPnt + 1L);
    2717 [ #  # ][ #  # ]:          0 :                         SetPathPoly(basegfx::B2DPolyPolygon(aSplitPolyA));
                 [ #  # ]
    2718                 :            : 
    2719         [ #  # ]:          0 :                         pNewObj = (SdrPathObj*)Clone();
    2720         [ #  # ]:          0 :                         basegfx::B2DPolygon aSplitPolyB(aCandidate, nPnt, nPointCount - nPnt);
    2721 [ #  # ][ #  # ]:          0 :                         pNewObj->SetPathPoly(basegfx::B2DPolyPolygon(aSplitPolyB));
         [ #  # ][ #  # ]
                 [ #  # ]
    2722                 :            :                     }
    2723                 :            :                 }
    2724         [ #  # ]:          0 :             }
    2725                 :            :         }
    2726                 :            :     }
    2727                 :            : 
    2728         [ #  # ]:          0 :     return pNewObj;
    2729                 :            : }
    2730                 :            : 
    2731                 :         26 : SdrObject* SdrPathObj::DoConvertToPolyObj(sal_Bool bBezier) const
    2732                 :            : {
    2733                 :            :     // #i89784# check for FontWork with activated HideContour
    2734                 :            :     const drawinglayer::attribute::SdrTextAttribute aText(
    2735 [ +  - ][ +  - ]:         26 :         drawinglayer::primitive2d::createNewSdrTextAttribute(GetObjectItemSet(), *getText(0)));
                 [ +  - ]
    2736                 :            :     const bool bHideContour(
    2737 [ +  - ][ -  + ]:         26 :         !aText.isDefault() && !aText.getSdrFormTextAttribute().isDefault() && aText.isHideContour());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    2738                 :            : 
    2739                 :            :     SdrObject* pRet = bHideContour ?
    2740                 :            :         0 :
    2741 [ -  + ][ +  - ]:         26 :         ImpConvertMakeObj(GetPathPoly(), IsClosed(), bBezier);
    2742                 :            : 
    2743 [ +  - ][ +  - ]:         26 :     SdrPathObj* pPath = PTR_CAST(SdrPathObj, pRet);
         [ +  - ][ +  - ]
    2744                 :            : 
    2745         [ +  - ]:         26 :     if(pPath)
    2746                 :            :     {
    2747 [ +  - ][ +  - ]:         26 :         if(pPath->GetPathPoly().areControlPointsUsed())
    2748                 :            :         {
    2749         [ -  + ]:         26 :             if(!bBezier)
    2750                 :            :             {
    2751                 :            :                 // reduce all bezier curves
    2752 [ #  # ][ #  # ]:          0 :                 pPath->SetPathPoly(basegfx::tools::adaptiveSubdivideByAngle(pPath->GetPathPoly()));
                 [ #  # ]
    2753                 :            :             }
    2754                 :            :         }
    2755                 :            :         else
    2756                 :            :         {
    2757         [ #  # ]:          0 :             if(bBezier)
    2758                 :            :             {
    2759                 :            :                 // create bezier curves
    2760 [ #  # ][ #  # ]:          0 :                 pPath->SetPathPoly(basegfx::tools::expandToCurve(pPath->GetPathPoly()));
                 [ #  # ]
    2761                 :            :             }
    2762                 :            :         }
    2763                 :            :     }
    2764                 :            : 
    2765         [ +  - ]:         26 :     pRet = ImpConvertAddText(pRet, bBezier);
    2766                 :            : 
    2767         [ +  - ]:         26 :     return pRet;
    2768                 :            : }
    2769                 :            : 
    2770                 :          0 : SdrObjGeoData* SdrPathObj::NewGeoData() const
    2771                 :            : {
    2772         [ #  # ]:          0 :     return new SdrPathObjGeoData;
    2773                 :            : }
    2774                 :            : 
    2775                 :          0 : void SdrPathObj::SaveGeoData(SdrObjGeoData& rGeo) const
    2776                 :            : {
    2777                 :          0 :     SdrTextObj::SaveGeoData(rGeo);
    2778                 :          0 :     SdrPathObjGeoData& rPGeo = (SdrPathObjGeoData&) rGeo;
    2779                 :          0 :     rPGeo.maPathPolygon=GetPathPoly();
    2780                 :          0 :     rPGeo.meKind=meKind;
    2781                 :          0 : }
    2782                 :            : 
    2783                 :          0 : void SdrPathObj::RestGeoData(const SdrObjGeoData& rGeo)
    2784                 :            : {
    2785                 :          0 :     SdrTextObj::RestGeoData(rGeo);
    2786                 :          0 :     SdrPathObjGeoData& rPGeo=(SdrPathObjGeoData&)rGeo;
    2787                 :          0 :     maPathPolygon=rPGeo.maPathPolygon;
    2788                 :          0 :     meKind=rPGeo.meKind;
    2789                 :          0 :     ImpForceKind(); // to set bClosed (among other things)
    2790                 :          0 : }
    2791                 :            : 
    2792                 :      17349 : void SdrPathObj::NbcSetPathPoly(const basegfx::B2DPolyPolygon& rPathPoly)
    2793                 :            : {
    2794         [ +  - ]:      17349 :     if(GetPathPoly() != rPathPoly)
    2795                 :            :     {
    2796                 :      17349 :         maPathPolygon=rPathPoly;
    2797                 :      17349 :         ImpForceKind();
    2798                 :      17349 :         SetRectsDirty();
    2799                 :            :     }
    2800                 :      17349 : }
    2801                 :            : 
    2802                 :      17361 : void SdrPathObj::SetPathPoly(const basegfx::B2DPolyPolygon& rPathPoly)
    2803                 :            : {
    2804         [ +  + ]:      17361 :     if(GetPathPoly() != rPathPoly)
    2805                 :            :     {
    2806 [ +  - ][ -  + ]:      17349 :         Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
                 [ #  # ]
    2807         [ +  - ]:      17349 :         NbcSetPathPoly(rPathPoly);
    2808         [ +  - ]:      17349 :         SetChanged();
    2809         [ +  - ]:      17349 :         BroadcastObjectChange();
    2810         [ +  - ]:      17349 :         SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
    2811                 :            :     }
    2812                 :      17361 : }
    2813                 :            : 
    2814                 :          0 : void SdrPathObj::ToggleClosed()
    2815                 :            : {
    2816         [ #  # ]:          0 :     Rectangle aBoundRect0;
    2817         [ #  # ]:          0 :     if(pUserCall != NULL)
    2818         [ #  # ]:          0 :         aBoundRect0 = GetLastBoundRect();
    2819         [ #  # ]:          0 :     ImpSetClosed(!IsClosed()); // set new ObjKind
    2820         [ #  # ]:          0 :     ImpForceKind(); // because we want Line -> Poly -> PolyLine instead of Line -> Poly -> Line
    2821         [ #  # ]:          0 :     SetRectsDirty();
    2822         [ #  # ]:          0 :     SetChanged();
    2823         [ #  # ]:          0 :     BroadcastObjectChange();
    2824         [ #  # ]:          0 :     SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
    2825                 :          0 : }
    2826                 :            : 
    2827                 :            : // for friend class SdrPolyEditView in some compilers:
    2828                 :     180346 : void SdrPathObj::SetRectsDirty(sal_Bool bNotMyself)
    2829                 :            : {
    2830                 :     180346 :     SdrTextObj::SetRectsDirty(bNotMyself);
    2831                 :     180346 : }
    2832                 :            : 
    2833                 :          0 : ImpPathForDragAndCreate& SdrPathObj::impGetDAC() const
    2834                 :            : {
    2835         [ #  # ]:          0 :     if(!mpDAC)
    2836                 :            :     {
    2837         [ #  # ]:          0 :         ((SdrPathObj*)this)->mpDAC = new ImpPathForDragAndCreate(*((SdrPathObj*)this));
    2838                 :            :     }
    2839                 :            : 
    2840                 :          0 :     return *mpDAC;
    2841                 :            : }
    2842                 :            : 
    2843                 :      19536 : void SdrPathObj::impDeleteDAC() const
    2844                 :            : {
    2845         [ -  + ]:      19536 :     if(mpDAC)
    2846                 :            :     {
    2847         [ #  # ]:          0 :         delete mpDAC;
    2848                 :          0 :         ((SdrPathObj*)this)->mpDAC = 0L;
    2849                 :            :     }
    2850                 :      19536 : }
    2851                 :            : 
    2852                 :            : ////////////////////////////////////////////////////////////////////////////////////////////////////
    2853                 :            : //
    2854                 :            : // transformation interface for StarOfficeAPI. This implements support for
    2855                 :            : // homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
    2856                 :            : // moment it contains a shearX, rotation and translation, but for setting all linear
    2857                 :            : // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
    2858                 :            : //
    2859                 :            : ////////////////////////////////////////////////////////////////////////////////////////////////////
    2860                 :            : // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
    2861                 :            : // with the base geometry and returns TRUE. Otherwise it returns FALSE.
    2862                 :        142 : sal_Bool SdrPathObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& rPolyPolygon) const
    2863                 :            : {
    2864                 :        142 :     double fRotate(0.0);
    2865                 :        142 :     double fShearX(0.0);
    2866                 :        142 :     basegfx::B2DTuple aScale(1.0, 1.0);
    2867                 :        142 :     basegfx::B2DTuple aTranslate(0.0, 0.0);
    2868                 :            : 
    2869 [ +  + ][ +  - ]:        142 :     if(GetPathPoly().count())
    2870                 :            :     {
    2871                 :            :         // copy geometry
    2872         [ +  - ]:        104 :         basegfx::B2DHomMatrix aMoveToZeroMatrix;
    2873         [ +  - ]:        104 :         rPolyPolygon = GetPathPoly();
    2874                 :            : 
    2875         [ +  + ]:        104 :         if(OBJ_LINE == meKind)
    2876                 :            :         {
    2877                 :            :             // ignore shear and rotate, just use scale and translate
    2878                 :            :             OSL_ENSURE(GetPathPoly().count() > 0L && GetPathPoly().getB2DPolygon(0L).count() > 1L, "OBJ_LINE with too few polygons (!)");
    2879                 :            :             // #i72287# use polygon without control points for range calculation. Do not change rPolyPolygon
    2880                 :            :             // itself, else this method will no longer return the full polygon information (curve will
    2881                 :            :             // be lost)
    2882         [ +  - ]:         32 :             const basegfx::B2DRange aPolyRangeNoCurve(basegfx::tools::getRange(rPolyPolygon));
    2883         [ +  - ]:         32 :             aScale = aPolyRangeNoCurve.getRange();
    2884         [ +  - ]:         32 :             aTranslate = aPolyRangeNoCurve.getMinimum();
    2885                 :            : 
    2886                 :            :             // define matrix for move polygon to zero point
    2887         [ +  - ]:         32 :             aMoveToZeroMatrix.translate(-aTranslate.getX(), -aTranslate.getY());
    2888                 :            :         }
    2889                 :            :         else
    2890                 :            :         {
    2891 [ +  - ][ +  + ]:         72 :             if(aGeo.nShearWink || aGeo.nDrehWink)
    2892                 :            :             {
    2893                 :            :                 // get rotate and shear in drawingLayer notation
    2894                 :         24 :                 fRotate = aGeo.nDrehWink * F_PI18000;
    2895                 :         24 :                 fShearX = aGeo.nShearWink * F_PI18000;
    2896                 :            : 
    2897                 :            :                 // build mathematically correct (negative shear and rotate) object transform
    2898                 :            :                 // containing shear and rotate to extract unsheared, unrotated polygon
    2899         [ +  - ]:         24 :                 basegfx::B2DHomMatrix aObjectMatrix;
    2900         [ +  - ]:         24 :                 aObjectMatrix.shearX(tan((36000 - aGeo.nShearWink) * F_PI18000));
    2901         [ +  - ]:         24 :                 aObjectMatrix.rotate((36000 - aGeo.nDrehWink) * F_PI18000);
    2902                 :            : 
    2903                 :            :                 // create inverse from it and back-transform polygon
    2904         [ +  - ]:         24 :                 basegfx::B2DHomMatrix aInvObjectMatrix(aObjectMatrix);
    2905         [ +  - ]:         24 :                 aInvObjectMatrix.invert();
    2906         [ +  - ]:         24 :                 rPolyPolygon.transform(aInvObjectMatrix);
    2907                 :            : 
    2908                 :            :                 // get range from unsheared, unrotated polygon and extract scale and translate.
    2909                 :            :                 // transform topLeft from it back to transformed state to get original
    2910                 :            :                 // topLeft (rotation center)
    2911                 :            :                 // #i72287# use polygon without control points for range calculation. Do not change rPolyPolygon
    2912                 :            :                 // itself, else this method will no longer return the full polygon information (curve will
    2913                 :            :                 // be lost)
    2914         [ +  - ]:         24 :                 const basegfx::B2DRange aCorrectedRangeNoCurve(basegfx::tools::getRange(rPolyPolygon));
    2915 [ +  - ][ +  - ]:         24 :                 aTranslate = aObjectMatrix * aCorrectedRangeNoCurve.getMinimum();
    2916         [ +  - ]:         24 :                 aScale = aCorrectedRangeNoCurve.getRange();
    2917                 :            : 
    2918                 :            :                 // define matrix for move polygon to zero point
    2919                 :            :                 // #i112280# Added missing minus for Y-Translation
    2920 [ +  - ][ +  - ]:         24 :                 aMoveToZeroMatrix.translate(-aCorrectedRangeNoCurve.getMinX(), -aCorrectedRangeNoCurve.getMinY());
         [ +  - ][ +  - ]
                 [ +  - ]
    2921                 :            :             }
    2922                 :            :             else
    2923                 :            :             {
    2924                 :            :                 // get scale and translate from unsheared, unrotated polygon
    2925                 :            :                 // #i72287# use polygon without control points for range calculation. Do not change rPolyPolygon
    2926                 :            :                 // itself, else this method will no longer return the full polygon information (curve will
    2927                 :            :                 // be lost)
    2928         [ +  - ]:         48 :                 const basegfx::B2DRange aPolyRangeNoCurve(basegfx::tools::getRange(rPolyPolygon));
    2929         [ +  - ]:         48 :                 aScale = aPolyRangeNoCurve.getRange();
    2930         [ +  - ]:         48 :                 aTranslate = aPolyRangeNoCurve.getMinimum();
    2931                 :            : 
    2932                 :            :                 // define matrix for move polygon to zero point
    2933         [ +  - ]:         48 :                 aMoveToZeroMatrix.translate(-aTranslate.getX(), -aTranslate.getY());
    2934                 :            :             }
    2935                 :            :         }
    2936                 :            : 
    2937                 :            :         // move polygon to zero point with pre-defined matrix
    2938 [ +  - ][ +  - ]:        104 :         rPolyPolygon.transform(aMoveToZeroMatrix);
    2939                 :            :     }
    2940                 :            : 
    2941                 :            :     // position maybe relative to anchorpos, convert
    2942 [ +  - ][ -  + ]:        142 :     if( pModel && pModel->IsWriter() )
                 [ -  + ]
    2943                 :            :     {
    2944 [ #  # ][ #  # ]:          0 :         if(GetAnchorPos().X() || GetAnchorPos().Y())
         [ #  # ][ #  # ]
                 [ #  # ]
    2945                 :            :         {
    2946 [ #  # ][ #  # ]:          0 :             aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
    2947                 :            :         }
    2948                 :            :     }
    2949                 :            : 
    2950                 :            :     // force MapUnit to 100th mm
    2951 [ +  - ][ +  - ]:        142 :     SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0);
    2952         [ -  + ]:        142 :     if(eMapUnit != SFX_MAPUNIT_100TH_MM)
    2953                 :            :     {
    2954         [ #  # ]:          0 :         switch(eMapUnit)
    2955                 :            :         {
    2956                 :            :             case SFX_MAPUNIT_TWIP :
    2957                 :            :             {
    2958                 :            :                 // position
    2959                 :          0 :                 aTranslate.setX(ImplTwipsToMM(aTranslate.getX()));
    2960                 :          0 :                 aTranslate.setY(ImplTwipsToMM(aTranslate.getY()));
    2961                 :            : 
    2962                 :            :                 // size
    2963                 :          0 :                 aScale.setX(ImplTwipsToMM(aScale.getX()));
    2964                 :          0 :                 aScale.setY(ImplTwipsToMM(aScale.getY()));
    2965                 :            : 
    2966                 :            :                 // polygon
    2967         [ #  # ]:          0 :                 basegfx::B2DHomMatrix aTwipsToMM;
    2968                 :          0 :                 const double fFactorTwipsToMM(127.0 / 72.0);
    2969         [ #  # ]:          0 :                 aTwipsToMM.scale(fFactorTwipsToMM, fFactorTwipsToMM);
    2970         [ #  # ]:          0 :                 rPolyPolygon.transform(aTwipsToMM);
    2971                 :            : 
    2972         [ #  # ]:          0 :                 break;
    2973                 :            :             }
    2974                 :            :             default:
    2975                 :            :             {
    2976                 :            :                 OSL_FAIL("TRGetBaseGeometry: Missing unit translation to 100th mm!");
    2977                 :            :             }
    2978                 :            :         }
    2979                 :            :     }
    2980                 :            : 
    2981                 :            :     // build return value matrix
    2982                 :            :     rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
    2983                 :            :         aScale,
    2984                 :        142 :         basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX),
    2985                 :        142 :         basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate,
    2986 [ +  - ][ +  - ]:        284 :         aTranslate);
         [ +  - ][ +  - ]
                 [ +  + ]
    2987                 :            : 
    2988                 :        142 :     return sal_True;
    2989                 :            : }
    2990                 :            : 
    2991                 :            : // Sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
    2992                 :            : // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
    2993                 :            : // to use (0,0) as upper left and will be scaled to the given size in the matrix.
    2994                 :         76 : void SdrPathObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& rPolyPolygon)
    2995                 :            : {
    2996                 :            :     // break up matrix
    2997                 :         76 :     basegfx::B2DTuple aScale;
    2998                 :         76 :     basegfx::B2DTuple aTranslate;
    2999                 :            :     double fRotate, fShearX;
    3000         [ +  - ]:         76 :     rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
    3001                 :            : 
    3002                 :            :     // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
    3003                 :            :     // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
    3004 [ -  + ][ #  # ]:         76 :     if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
         [ -  + ][ -  + ]
         [ +  - ][ +  - ]
                 [ -  + ]
    3005                 :            :     {
    3006                 :          0 :         aScale.setX(fabs(aScale.getX()));
    3007                 :          0 :         aScale.setY(fabs(aScale.getY()));
    3008                 :          0 :         fRotate = fmod(fRotate + F_PI, F_2PI);
    3009                 :            :     }
    3010                 :            : 
    3011                 :            :     // copy poly
    3012         [ +  - ]:         76 :     basegfx::B2DPolyPolygon aNewPolyPolygon(rPolyPolygon);
    3013                 :            : 
    3014                 :            :     // reset object shear and rotations
    3015                 :         76 :     aGeo.nDrehWink = 0;
    3016         [ +  - ]:         76 :     aGeo.RecalcSinCos();
    3017                 :         76 :     aGeo.nShearWink = 0;
    3018         [ +  - ]:         76 :     aGeo.RecalcTan();
    3019                 :            : 
    3020                 :            :     // force metric to pool metric
    3021 [ +  - ][ +  - ]:         76 :     SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0);
    3022         [ -  + ]:         76 :     if(eMapUnit != SFX_MAPUNIT_100TH_MM)
    3023                 :            :     {
    3024         [ #  # ]:          0 :         switch(eMapUnit)
    3025                 :            :         {
    3026                 :            :             case SFX_MAPUNIT_TWIP :
    3027                 :            :             {
    3028                 :            :                 // position
    3029                 :          0 :                 aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
    3030                 :          0 :                 aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
    3031                 :            : 
    3032                 :            :                 // size
    3033                 :          0 :                 aScale.setX(ImplMMToTwips(aScale.getX()));
    3034                 :          0 :                 aScale.setY(ImplMMToTwips(aScale.getY()));
    3035                 :            : 
    3036                 :            :                 // polygon
    3037         [ #  # ]:          0 :                 basegfx::B2DHomMatrix aMMToTwips;
    3038                 :          0 :                 const double fFactorMMToTwips(72.0 / 127.0);
    3039         [ #  # ]:          0 :                 aMMToTwips.scale(fFactorMMToTwips, fFactorMMToTwips);
    3040         [ #  # ]:          0 :                 aNewPolyPolygon.transform(aMMToTwips);
    3041                 :            : 
    3042         [ #  # ]:          0 :                 break;
    3043                 :            :             }
    3044                 :            :             default:
    3045                 :            :             {
    3046                 :            :                 OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
    3047                 :            :             }
    3048                 :            :         }
    3049                 :            :     }
    3050                 :            : 
    3051 [ +  - ][ -  + ]:         76 :     if( pModel && pModel->IsWriter() )
                 [ -  + ]
    3052                 :            :     {
    3053                 :            :         // if anchor is used, make position relative to it
    3054 [ #  # ][ #  # ]:          0 :         if(GetAnchorPos().X() || GetAnchorPos().Y())
         [ #  # ][ #  # ]
                 [ #  # ]
    3055                 :            :         {
    3056 [ #  # ][ #  # ]:          0 :             aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
    3057                 :            :         }
    3058                 :            :     }
    3059                 :            : 
    3060                 :            :     // create transformation for polygon, set values at aGeo direct
    3061         [ +  - ]:         76 :     basegfx::B2DHomMatrix aTransform;
    3062                 :            : 
    3063                 :            :     // #i75086#
    3064                 :            :     // Given polygon is already scaled (for historical reasons), but not mirrored yet.
    3065                 :            :     // Thus, when scale is negative in X or Y, apply the needed mirroring accordingly.
    3066 [ +  - ][ -  + ]:         76 :     if(basegfx::fTools::less(aScale.getX(), 0.0) || basegfx::fTools::less(aScale.getY(), 0.0))
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
    3067                 :            :     {
    3068                 :            :         aTransform.scale(
    3069                 :          0 :             basegfx::fTools::less(aScale.getX(), 0.0) ? -1.0 : 1.0,
    3070 [ #  # ][ #  # ]:          0 :             basegfx::fTools::less(aScale.getY(), 0.0) ? -1.0 : 1.0);
                 [ #  # ]
    3071                 :            :     }
    3072                 :            : 
    3073         [ -  + ]:         76 :     if(!basegfx::fTools::equalZero(fShearX))
    3074                 :            :     {
    3075         [ #  # ]:          0 :         aTransform.shearX(tan(-atan(fShearX)));
    3076                 :          0 :         aGeo.nShearWink = FRound(atan(fShearX) / F_PI18000);
    3077         [ #  # ]:          0 :         aGeo.RecalcTan();
    3078                 :            :     }
    3079                 :            : 
    3080         [ +  + ]:         76 :     if(!basegfx::fTools::equalZero(fRotate))
    3081                 :            :     {
    3082                 :            :         // #i78696#
    3083                 :            :         // fRotate is mathematically correct for linear transformations, so it's
    3084                 :            :         // the one to use for the geometry change
    3085         [ +  - ]:         12 :         aTransform.rotate(fRotate);
    3086                 :            : 
    3087                 :            :         // #i78696#
    3088                 :            :         // fRotate is mathematically correct, but aGeoStat.nDrehWink is
    3089                 :            :         // mirrored -> mirror value here
    3090         [ +  - ]:         12 :         aGeo.nDrehWink = NormAngle360(FRound(-fRotate / F_PI18000));
    3091         [ +  - ]:         12 :         aGeo.RecalcSinCos();
    3092                 :            :     }
    3093                 :            : 
    3094 [ +  - ][ +  + ]:         76 :     if(!aTranslate.equalZero())
    3095                 :            :     {
    3096                 :            :         // #i39529# absolute positioning, so get current position (without control points (!))
    3097         [ +  - ]:         38 :         const basegfx::B2DRange aCurrentRange(basegfx::tools::getRange(aNewPolyPolygon));
    3098 [ +  - ][ +  - ]:         38 :         aTransform.translate(aTranslate.getX() - aCurrentRange.getMinX(), aTranslate.getY() - aCurrentRange.getMinY());
                 [ +  - ]
    3099                 :            :     }
    3100                 :            : 
    3101                 :            :     // transform polygon and trigger change
    3102         [ +  - ]:         76 :     aNewPolyPolygon.transform(aTransform);
    3103 [ +  - ][ +  - ]:         76 :     SetPathPoly(aNewPolyPolygon);
                 [ +  - ]
    3104                 :         76 : }
    3105                 :            : 
    3106                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10