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