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