xref: /AOO41X/main/svx/source/svdraw/svdocirc.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_svx.hxx"
30*cdf0e10cSrcweir #include <svl/style.hxx>
31*cdf0e10cSrcweir #include <tools/bigint.hxx>
32*cdf0e10cSrcweir #include <svx/xlnwtit.hxx>
33*cdf0e10cSrcweir #include <svx/xlnedwit.hxx>
34*cdf0e10cSrcweir #include <svx/xlnstwit.hxx>
35*cdf0e10cSrcweir #include <svx/xlnstit.hxx>
36*cdf0e10cSrcweir #include <svx/xlnedit.hxx>
37*cdf0e10cSrcweir #include <svx/svdocirc.hxx>
38*cdf0e10cSrcweir #include <math.h>
39*cdf0e10cSrcweir #include <svx/xpool.hxx>
40*cdf0e10cSrcweir #include <svx/svdattr.hxx>
41*cdf0e10cSrcweir #include <svx/svdpool.hxx>
42*cdf0e10cSrcweir #include <svx/svdattrx.hxx>
43*cdf0e10cSrcweir #include <svx/svdtrans.hxx>
44*cdf0e10cSrcweir #include <svx/svdetc.hxx>
45*cdf0e10cSrcweir #include <svx/svddrag.hxx>
46*cdf0e10cSrcweir #include <svx/svdmodel.hxx>
47*cdf0e10cSrcweir #include <svx/svdpage.hxx>
48*cdf0e10cSrcweir #include <svx/svdopath.hxx> // fuer die Objektkonvertierung
49*cdf0e10cSrcweir #include <svx/svdview.hxx>  // Zum Draggen (Ortho)
50*cdf0e10cSrcweir #include "svx/svdglob.hxx"   // StringCache
51*cdf0e10cSrcweir #include "svx/svdstr.hrc"    // Objektname
52*cdf0e10cSrcweir #include <editeng/eeitem.hxx>
53*cdf0e10cSrcweir #include "svdoimp.hxx"
54*cdf0e10cSrcweir #include <svx/sdr/properties/circleproperties.hxx>
55*cdf0e10cSrcweir #include <svx/sdr/contact/viewcontactofsdrcircobj.hxx>
56*cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
57*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
58*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
59*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
60*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
61*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx>
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
64*cdf0e10cSrcweir 
65*cdf0e10cSrcweir Point GetWinkPnt(const Rectangle& rR, long nWink)
66*cdf0e10cSrcweir {
67*cdf0e10cSrcweir 	Point aCenter(rR.Center());
68*cdf0e10cSrcweir 	long nWdt=rR.Right()-rR.Left();
69*cdf0e10cSrcweir 	long nHgt=rR.Bottom()-rR.Top();
70*cdf0e10cSrcweir 	long nMaxRad=((nWdt>nHgt ? nWdt : nHgt)+1) /2;
71*cdf0e10cSrcweir 	double a;
72*cdf0e10cSrcweir 	a=nWink*nPi180;
73*cdf0e10cSrcweir 	Point aRetval(Round(cos(a)*nMaxRad),-Round(sin(a)*nMaxRad));
74*cdf0e10cSrcweir 	if (nWdt==0) aRetval.X()=0;
75*cdf0e10cSrcweir 	if (nHgt==0) aRetval.Y()=0;
76*cdf0e10cSrcweir 	if (nWdt!=nHgt) {
77*cdf0e10cSrcweir 		if (nWdt>nHgt) {
78*cdf0e10cSrcweir 			if (nWdt!=0) {
79*cdf0e10cSrcweir 				// eventuelle Ueberlaeufe bei sehr grossen Objekten abfangen (Bug 23384)
80*cdf0e10cSrcweir 				if (Abs(nHgt)>32767 || Abs(aRetval.Y())>32767) {
81*cdf0e10cSrcweir 					aRetval.Y()=BigMulDiv(aRetval.Y(),nHgt,nWdt);
82*cdf0e10cSrcweir 				} else {
83*cdf0e10cSrcweir 					aRetval.Y()=aRetval.Y()*nHgt/nWdt;
84*cdf0e10cSrcweir 				}
85*cdf0e10cSrcweir 			}
86*cdf0e10cSrcweir 		} else {
87*cdf0e10cSrcweir 			if (nHgt!=0) {
88*cdf0e10cSrcweir 				// eventuelle Ueberlaeufe bei sehr grossen Objekten abfangen (Bug 23384)
89*cdf0e10cSrcweir 				if (Abs(nWdt)>32767 || Abs(aRetval.X())>32767) {
90*cdf0e10cSrcweir 					aRetval.X()=BigMulDiv(aRetval.X(),nWdt,nHgt);
91*cdf0e10cSrcweir 				} else {
92*cdf0e10cSrcweir 					aRetval.X()=aRetval.X()*nWdt/nHgt;
93*cdf0e10cSrcweir 				}
94*cdf0e10cSrcweir 			}
95*cdf0e10cSrcweir 		}
96*cdf0e10cSrcweir 	}
97*cdf0e10cSrcweir 	aRetval+=aCenter;
98*cdf0e10cSrcweir     return aRetval;
99*cdf0e10cSrcweir }
100*cdf0e10cSrcweir 
101*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
102*cdf0e10cSrcweir // BaseProperties section
103*cdf0e10cSrcweir 
104*cdf0e10cSrcweir sdr::properties::BaseProperties* SdrCircObj::CreateObjectSpecificProperties()
105*cdf0e10cSrcweir {
106*cdf0e10cSrcweir 	return new sdr::properties::CircleProperties(*this);
107*cdf0e10cSrcweir }
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
110*cdf0e10cSrcweir // DrawContact section
111*cdf0e10cSrcweir 
112*cdf0e10cSrcweir sdr::contact::ViewContact* SdrCircObj::CreateObjectSpecificViewContact()
113*cdf0e10cSrcweir {
114*cdf0e10cSrcweir 	return new sdr::contact::ViewContactOfSdrCircObj(*this);
115*cdf0e10cSrcweir }
116*cdf0e10cSrcweir 
117*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
118*cdf0e10cSrcweir 
119*cdf0e10cSrcweir TYPEINIT1(SdrCircObj,SdrRectObj);
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir SdrCircObj::SdrCircObj(SdrObjKind eNewKind)
122*cdf0e10cSrcweir {
123*cdf0e10cSrcweir 	nStartWink=0;
124*cdf0e10cSrcweir 	nEndWink=36000;
125*cdf0e10cSrcweir 	meCircleKind=eNewKind;
126*cdf0e10cSrcweir 	bClosedObj=eNewKind!=OBJ_CARC;
127*cdf0e10cSrcweir }
128*cdf0e10cSrcweir 
129*cdf0e10cSrcweir SdrCircObj::SdrCircObj(SdrObjKind eNewKind, const Rectangle& rRect):
130*cdf0e10cSrcweir 	SdrRectObj(rRect)
131*cdf0e10cSrcweir {
132*cdf0e10cSrcweir 	nStartWink=0;
133*cdf0e10cSrcweir 	nEndWink=36000;
134*cdf0e10cSrcweir 	meCircleKind=eNewKind;
135*cdf0e10cSrcweir 	bClosedObj=eNewKind!=OBJ_CARC;
136*cdf0e10cSrcweir }
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir SdrCircObj::SdrCircObj(SdrObjKind eNewKind, const Rectangle& rRect, long nNewStartWink, long nNewEndWink):
139*cdf0e10cSrcweir 	SdrRectObj(rRect)
140*cdf0e10cSrcweir {
141*cdf0e10cSrcweir 	long nWinkDif=nNewEndWink-nNewStartWink;
142*cdf0e10cSrcweir 	nStartWink=NormAngle360(nNewStartWink);
143*cdf0e10cSrcweir 	nEndWink=NormAngle360(nNewEndWink);
144*cdf0e10cSrcweir 	if (nWinkDif==36000) nEndWink+=nWinkDif; // Vollkreis
145*cdf0e10cSrcweir 	meCircleKind=eNewKind;
146*cdf0e10cSrcweir 	bClosedObj=eNewKind!=OBJ_CARC;
147*cdf0e10cSrcweir }
148*cdf0e10cSrcweir 
149*cdf0e10cSrcweir SdrCircObj::~SdrCircObj()
150*cdf0e10cSrcweir {
151*cdf0e10cSrcweir }
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir void SdrCircObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
154*cdf0e10cSrcweir {
155*cdf0e10cSrcweir 	FASTBOOL bCanConv=!HasText() || ImpCanConvTextToCurve();
156*cdf0e10cSrcweir 	rInfo.bEdgeRadiusAllowed	= sal_False;
157*cdf0e10cSrcweir 	rInfo.bCanConvToPath=bCanConv;
158*cdf0e10cSrcweir 	rInfo.bCanConvToPoly=bCanConv;
159*cdf0e10cSrcweir 	rInfo.bCanConvToContour = !IsFontwork() && (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
160*cdf0e10cSrcweir }
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir sal_uInt16 SdrCircObj::GetObjIdentifier() const
163*cdf0e10cSrcweir {
164*cdf0e10cSrcweir 	return sal_uInt16(meCircleKind);
165*cdf0e10cSrcweir }
166*cdf0e10cSrcweir 
167*cdf0e10cSrcweir FASTBOOL SdrCircObj::PaintNeedsXPolyCirc() const
168*cdf0e10cSrcweir {
169*cdf0e10cSrcweir 	// XPoly ist notwendig fuer alle gedrehten Ellipsenobjekte,
170*cdf0e10cSrcweir 	// fuer alle Kreis- und Ellipsenabschnitte
171*cdf0e10cSrcweir 	// und wenn nicht WIN dann (erstmal) auch fuer Kreis-/Ellipsenausschnitte
172*cdf0e10cSrcweir 	// und Kreis-/Ellipsenboegen (wg. Genauigkeit)
173*cdf0e10cSrcweir 	FASTBOOL bNeed=aGeo.nDrehWink!=0 || aGeo.nShearWink!=0 || meCircleKind==OBJ_CCUT;
174*cdf0e10cSrcweir 	// Wenn nicht Win, dann fuer alle ausser Vollkreis (erstmal!!!)
175*cdf0e10cSrcweir 	if (meCircleKind!=OBJ_CIRC) bNeed=sal_True;
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir 	const SfxItemSet& rSet = GetObjectItemSet();
178*cdf0e10cSrcweir 	if(!bNeed)
179*cdf0e10cSrcweir 	{
180*cdf0e10cSrcweir 		// XPoly ist notwendig fuer alles was nicht LineSolid oder LineNone ist
181*cdf0e10cSrcweir 		XLineStyle eLine = ((XLineStyleItem&)(rSet.Get(XATTR_LINESTYLE))).GetValue();
182*cdf0e10cSrcweir 		bNeed = eLine != XLINE_NONE && eLine != XLINE_SOLID;
183*cdf0e10cSrcweir 
184*cdf0e10cSrcweir 		// XPoly ist notwendig fuer dicke Linien
185*cdf0e10cSrcweir 		if(!bNeed && eLine != XLINE_NONE)
186*cdf0e10cSrcweir 			bNeed = ((XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue() != 0;
187*cdf0e10cSrcweir 
188*cdf0e10cSrcweir 		// XPoly ist notwendig fuer Kreisboegen mit Linienenden
189*cdf0e10cSrcweir 		if(!bNeed && meCircleKind == OBJ_CARC)
190*cdf0e10cSrcweir 		{
191*cdf0e10cSrcweir 			// Linienanfang ist da, wenn StartPolygon und StartWidth!=0
192*cdf0e10cSrcweir 			bNeed=((XLineStartItem&)(rSet.Get(XATTR_LINESTART))).GetLineStartValue().count() != 0L &&
193*cdf0e10cSrcweir 				  ((XLineStartWidthItem&)(rSet.Get(XATTR_LINESTARTWIDTH))).GetValue() != 0;
194*cdf0e10cSrcweir 
195*cdf0e10cSrcweir 			if(!bNeed)
196*cdf0e10cSrcweir 			{
197*cdf0e10cSrcweir 				// Linienende ist da, wenn EndPolygon und EndWidth!=0
198*cdf0e10cSrcweir 				bNeed = ((XLineEndItem&)(rSet.Get(XATTR_LINEEND))).GetLineEndValue().count() != 0L &&
199*cdf0e10cSrcweir 						((XLineEndWidthItem&)(rSet.Get(XATTR_LINEENDWIDTH))).GetValue() != 0;
200*cdf0e10cSrcweir 			}
201*cdf0e10cSrcweir 		}
202*cdf0e10cSrcweir 	}
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir 	// XPoly ist notwendig, wenn Fill !=None und !=Solid
205*cdf0e10cSrcweir 	if(!bNeed && meCircleKind != OBJ_CARC)
206*cdf0e10cSrcweir 	{
207*cdf0e10cSrcweir 		XFillStyle eFill=((XFillStyleItem&)(rSet.Get(XATTR_FILLSTYLE))).GetValue();
208*cdf0e10cSrcweir 		bNeed = eFill != XFILL_NONE && eFill != XFILL_SOLID;
209*cdf0e10cSrcweir 	}
210*cdf0e10cSrcweir 
211*cdf0e10cSrcweir 	if(!bNeed && meCircleKind != OBJ_CIRC && nStartWink == nEndWink)
212*cdf0e10cSrcweir 		bNeed=sal_True; // Weil sonst Vollkreis gemalt wird
213*cdf0e10cSrcweir 
214*cdf0e10cSrcweir 	return bNeed;
215*cdf0e10cSrcweir }
216*cdf0e10cSrcweir 
217*cdf0e10cSrcweir basegfx::B2DPolygon SdrCircObj::ImpCalcXPolyCirc(const SdrObjKind eCicrleKind, const Rectangle& rRect1, long nStart, long nEnd) const
218*cdf0e10cSrcweir {
219*cdf0e10cSrcweir 	const basegfx::B2DRange aRange(rRect1.Left(), rRect1.Top(), rRect1.Right(), rRect1.Bottom());
220*cdf0e10cSrcweir 	basegfx::B2DPolygon aCircPolygon;
221*cdf0e10cSrcweir 
222*cdf0e10cSrcweir 	if(OBJ_CIRC == eCicrleKind)
223*cdf0e10cSrcweir 	{
224*cdf0e10cSrcweir 		// create full circle. Do not use createPolygonFromEllipse; it's necessary
225*cdf0e10cSrcweir         // to get the start point to the bottom of the circle to keep compatible to
226*cdf0e10cSrcweir         // old geometry creation
227*cdf0e10cSrcweir         aCircPolygon = basegfx::tools::createPolygonFromUnitCircle(1);
228*cdf0e10cSrcweir 
229*cdf0e10cSrcweir 		// needs own scaling and translation from unit circle to target size (same as
230*cdf0e10cSrcweir         // would be in createPolygonFromEllipse)
231*cdf0e10cSrcweir 		const basegfx::B2DPoint aCenter(aRange.getCenter());
232*cdf0e10cSrcweir 		const basegfx::B2DHomMatrix aMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix(
233*cdf0e10cSrcweir 			aRange.getWidth() / 2.0, aRange.getHeight() / 2.0,
234*cdf0e10cSrcweir 			aCenter.getX(), aCenter.getY()));
235*cdf0e10cSrcweir 		aCircPolygon.transform(aMatrix);
236*cdf0e10cSrcweir 	}
237*cdf0e10cSrcweir 	else
238*cdf0e10cSrcweir 	{
239*cdf0e10cSrcweir 		// mirror start, end for geometry creation since model coordinate system is mirrored in Y
240*cdf0e10cSrcweir         // #i111715# increase numerical correctness by first dividing and not using F_PI1800
241*cdf0e10cSrcweir 		const double fStart((((36000 - nEnd) % 36000) / 18000.0) * F_PI);
242*cdf0e10cSrcweir 		const double fEnd((((36000 - nStart) % 36000) / 18000.0) * F_PI);
243*cdf0e10cSrcweir 
244*cdf0e10cSrcweir 		// create circle segment. This is not closed by default
245*cdf0e10cSrcweir 		aCircPolygon = basegfx::tools::createPolygonFromEllipseSegment(
246*cdf0e10cSrcweir             aRange.getCenter(), aRange.getWidth() / 2.0, aRange.getHeight() / 2.0,
247*cdf0e10cSrcweir             fStart, fEnd);
248*cdf0e10cSrcweir 
249*cdf0e10cSrcweir 		// check closing states
250*cdf0e10cSrcweir 		const bool bCloseSegment(OBJ_CARC != eCicrleKind);
251*cdf0e10cSrcweir 		const bool bCloseUsingCenter(OBJ_SECT == eCicrleKind);
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir 		if(bCloseSegment)
254*cdf0e10cSrcweir 		{
255*cdf0e10cSrcweir 			if(bCloseUsingCenter)
256*cdf0e10cSrcweir 			{
257*cdf0e10cSrcweir 				// add center point at start (for historical reasons)
258*cdf0e10cSrcweir 				basegfx::B2DPolygon aSector;
259*cdf0e10cSrcweir 				aSector.append(aRange.getCenter());
260*cdf0e10cSrcweir 				aSector.append(aCircPolygon);
261*cdf0e10cSrcweir 				aCircPolygon = aSector;
262*cdf0e10cSrcweir 			}
263*cdf0e10cSrcweir 
264*cdf0e10cSrcweir 			// close
265*cdf0e10cSrcweir 			aCircPolygon.setClosed(true);
266*cdf0e10cSrcweir 		}
267*cdf0e10cSrcweir 	}
268*cdf0e10cSrcweir 
269*cdf0e10cSrcweir 	// #i76950#
270*cdf0e10cSrcweir 	if(aGeo.nShearWink || aGeo.nDrehWink)
271*cdf0e10cSrcweir 	{
272*cdf0e10cSrcweir 		// translate top left to (0,0)
273*cdf0e10cSrcweir 		const basegfx::B2DPoint aTopLeft(aRange.getMinimum());
274*cdf0e10cSrcweir         basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix(
275*cdf0e10cSrcweir             -aTopLeft.getX(), -aTopLeft.getY()));
276*cdf0e10cSrcweir 
277*cdf0e10cSrcweir 		// shear, rotate and back to top left (if needed)
278*cdf0e10cSrcweir         aMatrix = basegfx::tools::createShearXRotateTranslateB2DHomMatrix(
279*cdf0e10cSrcweir             aGeo.nShearWink ? tan((36000 - aGeo.nShearWink) * F_PI18000) : 0.0,
280*cdf0e10cSrcweir             aGeo.nDrehWink ? (36000 - aGeo.nDrehWink) * F_PI18000 : 0.0,
281*cdf0e10cSrcweir             aTopLeft) * aMatrix;
282*cdf0e10cSrcweir 
283*cdf0e10cSrcweir 		// apply transformation
284*cdf0e10cSrcweir 		aCircPolygon.transform(aMatrix);
285*cdf0e10cSrcweir 	}
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir 	return aCircPolygon;
288*cdf0e10cSrcweir }
289*cdf0e10cSrcweir 
290*cdf0e10cSrcweir void SdrCircObj::RecalcXPoly()
291*cdf0e10cSrcweir {
292*cdf0e10cSrcweir 	const basegfx::B2DPolygon aPolyCirc(ImpCalcXPolyCirc(meCircleKind, aRect, nStartWink, nEndWink));
293*cdf0e10cSrcweir 	mpXPoly = new XPolygon(aPolyCirc);
294*cdf0e10cSrcweir }
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir void SdrCircObj::TakeObjNameSingul(XubString& rName) const
297*cdf0e10cSrcweir {
298*cdf0e10cSrcweir 	sal_uInt16 nID=STR_ObjNameSingulCIRC;
299*cdf0e10cSrcweir 	if (aRect.GetWidth()==aRect.GetHeight() && aGeo.nShearWink==0) {
300*cdf0e10cSrcweir 		switch (meCircleKind) {
301*cdf0e10cSrcweir 			case OBJ_CIRC: nID=STR_ObjNameSingulCIRC; break;
302*cdf0e10cSrcweir 			case OBJ_SECT: nID=STR_ObjNameSingulSECT; break;
303*cdf0e10cSrcweir 			case OBJ_CARC: nID=STR_ObjNameSingulCARC; break;
304*cdf0e10cSrcweir 			case OBJ_CCUT: nID=STR_ObjNameSingulCCUT; break;
305*cdf0e10cSrcweir 			default: break;
306*cdf0e10cSrcweir 		}
307*cdf0e10cSrcweir 	} else {
308*cdf0e10cSrcweir 		switch (meCircleKind) {
309*cdf0e10cSrcweir 			case OBJ_CIRC: nID=STR_ObjNameSingulCIRCE; break;
310*cdf0e10cSrcweir 			case OBJ_SECT: nID=STR_ObjNameSingulSECTE; break;
311*cdf0e10cSrcweir 			case OBJ_CARC: nID=STR_ObjNameSingulCARCE; break;
312*cdf0e10cSrcweir 			case OBJ_CCUT: nID=STR_ObjNameSingulCCUTE; break;
313*cdf0e10cSrcweir 			default: break;
314*cdf0e10cSrcweir 		}
315*cdf0e10cSrcweir 	}
316*cdf0e10cSrcweir 	rName=ImpGetResStr(nID);
317*cdf0e10cSrcweir 
318*cdf0e10cSrcweir 	String aName( GetName() );
319*cdf0e10cSrcweir 	if(aName.Len())
320*cdf0e10cSrcweir 	{
321*cdf0e10cSrcweir 		rName += sal_Unicode(' ');
322*cdf0e10cSrcweir 		rName += sal_Unicode('\'');
323*cdf0e10cSrcweir 		rName += aName;
324*cdf0e10cSrcweir 		rName += sal_Unicode('\'');
325*cdf0e10cSrcweir 	}
326*cdf0e10cSrcweir }
327*cdf0e10cSrcweir 
328*cdf0e10cSrcweir void SdrCircObj::TakeObjNamePlural(XubString& rName) const
329*cdf0e10cSrcweir {
330*cdf0e10cSrcweir 	sal_uInt16 nID=STR_ObjNamePluralCIRC;
331*cdf0e10cSrcweir 	if (aRect.GetWidth()==aRect.GetHeight() && aGeo.nShearWink==0) {
332*cdf0e10cSrcweir 		switch (meCircleKind) {
333*cdf0e10cSrcweir 			case OBJ_CIRC: nID=STR_ObjNamePluralCIRC; break;
334*cdf0e10cSrcweir 			case OBJ_SECT: nID=STR_ObjNamePluralSECT; break;
335*cdf0e10cSrcweir 			case OBJ_CARC: nID=STR_ObjNamePluralCARC; break;
336*cdf0e10cSrcweir 			case OBJ_CCUT: nID=STR_ObjNamePluralCCUT; break;
337*cdf0e10cSrcweir 			default: break;
338*cdf0e10cSrcweir 		}
339*cdf0e10cSrcweir 	} else {
340*cdf0e10cSrcweir 		switch (meCircleKind) {
341*cdf0e10cSrcweir 			case OBJ_CIRC: nID=STR_ObjNamePluralCIRCE; break;
342*cdf0e10cSrcweir 			case OBJ_SECT: nID=STR_ObjNamePluralSECTE; break;
343*cdf0e10cSrcweir 			case OBJ_CARC: nID=STR_ObjNamePluralCARCE; break;
344*cdf0e10cSrcweir 			case OBJ_CCUT: nID=STR_ObjNamePluralCCUTE; break;
345*cdf0e10cSrcweir 			default: break;
346*cdf0e10cSrcweir 		}
347*cdf0e10cSrcweir 	}
348*cdf0e10cSrcweir 	rName=ImpGetResStr(nID);
349*cdf0e10cSrcweir }
350*cdf0e10cSrcweir 
351*cdf0e10cSrcweir void SdrCircObj::operator=(const SdrObject& rObj)
352*cdf0e10cSrcweir {
353*cdf0e10cSrcweir 	SdrRectObj::operator=(rObj);
354*cdf0e10cSrcweir 
355*cdf0e10cSrcweir 	nStartWink = ((SdrCircObj&)rObj).nStartWink;
356*cdf0e10cSrcweir 	nEndWink = ((SdrCircObj&)rObj).nEndWink;
357*cdf0e10cSrcweir }
358*cdf0e10cSrcweir 
359*cdf0e10cSrcweir basegfx::B2DPolyPolygon SdrCircObj::TakeXorPoly() const
360*cdf0e10cSrcweir {
361*cdf0e10cSrcweir 	const basegfx::B2DPolygon aCircPolygon(ImpCalcXPolyCirc(meCircleKind, aRect, nStartWink, nEndWink));
362*cdf0e10cSrcweir 	return basegfx::B2DPolyPolygon(aCircPolygon);
363*cdf0e10cSrcweir }
364*cdf0e10cSrcweir 
365*cdf0e10cSrcweir struct ImpCircUser : public SdrDragStatUserData
366*cdf0e10cSrcweir {
367*cdf0e10cSrcweir 	Rectangle					aR;
368*cdf0e10cSrcweir 	Point						aCenter;
369*cdf0e10cSrcweir 	Point						aRadius;
370*cdf0e10cSrcweir 	Point						aP1;
371*cdf0e10cSrcweir 	Point						aP2;
372*cdf0e10cSrcweir 	long						nMaxRad;
373*cdf0e10cSrcweir 	long						nHgt;
374*cdf0e10cSrcweir 	long						nWdt;
375*cdf0e10cSrcweir 	long						nStart;
376*cdf0e10cSrcweir 	long						nEnd;
377*cdf0e10cSrcweir 	long						nWink;
378*cdf0e10cSrcweir 	FASTBOOL					bRight; // noch nicht implementiert
379*cdf0e10cSrcweir 
380*cdf0e10cSrcweir public:
381*cdf0e10cSrcweir 	ImpCircUser()
382*cdf0e10cSrcweir 	:	nMaxRad(0),
383*cdf0e10cSrcweir 		nHgt(0),
384*cdf0e10cSrcweir 		nWdt(0),
385*cdf0e10cSrcweir 		nStart(0),
386*cdf0e10cSrcweir 		nEnd(0),
387*cdf0e10cSrcweir 		bRight(sal_False)
388*cdf0e10cSrcweir 	{}
389*cdf0e10cSrcweir 	void SetCreateParams(SdrDragStat& rStat);
390*cdf0e10cSrcweir };
391*cdf0e10cSrcweir 
392*cdf0e10cSrcweir sal_uInt32 SdrCircObj::GetHdlCount() const
393*cdf0e10cSrcweir {
394*cdf0e10cSrcweir 	if(OBJ_CIRC != meCircleKind)
395*cdf0e10cSrcweir 	{
396*cdf0e10cSrcweir 		return 10L;
397*cdf0e10cSrcweir 	}
398*cdf0e10cSrcweir 	else
399*cdf0e10cSrcweir 	{
400*cdf0e10cSrcweir 		return 8L;
401*cdf0e10cSrcweir 	}
402*cdf0e10cSrcweir }
403*cdf0e10cSrcweir 
404*cdf0e10cSrcweir SdrHdl* SdrCircObj::GetHdl(sal_uInt32 nHdlNum) const
405*cdf0e10cSrcweir {
406*cdf0e10cSrcweir 	if (meCircleKind==OBJ_CIRC)
407*cdf0e10cSrcweir     {
408*cdf0e10cSrcweir 		nHdlNum += 2L;
409*cdf0e10cSrcweir     }
410*cdf0e10cSrcweir 
411*cdf0e10cSrcweir     SdrHdl* pH = NULL;
412*cdf0e10cSrcweir 	Point aPnt;
413*cdf0e10cSrcweir 	SdrHdlKind eLocalKind(HDL_MOVE);
414*cdf0e10cSrcweir 	sal_uInt32 nPNum(0);
415*cdf0e10cSrcweir 
416*cdf0e10cSrcweir     switch (nHdlNum)
417*cdf0e10cSrcweir     {
418*cdf0e10cSrcweir 		case 0:
419*cdf0e10cSrcweir             aPnt = GetWinkPnt(aRect,nStartWink);
420*cdf0e10cSrcweir             eLocalKind = HDL_CIRC;
421*cdf0e10cSrcweir             nPNum = 1;
422*cdf0e10cSrcweir             break;
423*cdf0e10cSrcweir 		case 1:
424*cdf0e10cSrcweir             aPnt = GetWinkPnt(aRect,nEndWink);
425*cdf0e10cSrcweir             eLocalKind = HDL_CIRC;
426*cdf0e10cSrcweir             nPNum = 2L;
427*cdf0e10cSrcweir             break;
428*cdf0e10cSrcweir 		case 2:
429*cdf0e10cSrcweir             aPnt = aRect.TopLeft();
430*cdf0e10cSrcweir             eLocalKind = HDL_UPLFT;
431*cdf0e10cSrcweir             break;
432*cdf0e10cSrcweir 		case 3:
433*cdf0e10cSrcweir             aPnt = aRect.TopCenter();
434*cdf0e10cSrcweir             eLocalKind = HDL_UPPER;
435*cdf0e10cSrcweir             break;
436*cdf0e10cSrcweir 		case 4:
437*cdf0e10cSrcweir             aPnt = aRect.TopRight();
438*cdf0e10cSrcweir             eLocalKind = HDL_UPRGT;
439*cdf0e10cSrcweir             break;
440*cdf0e10cSrcweir 		case 5:
441*cdf0e10cSrcweir             aPnt = aRect.LeftCenter();
442*cdf0e10cSrcweir             eLocalKind = HDL_LEFT;
443*cdf0e10cSrcweir             break;
444*cdf0e10cSrcweir 		case 6:
445*cdf0e10cSrcweir             aPnt = aRect.RightCenter();
446*cdf0e10cSrcweir             eLocalKind = HDL_RIGHT;
447*cdf0e10cSrcweir             break;
448*cdf0e10cSrcweir 		case 7:
449*cdf0e10cSrcweir             aPnt = aRect.BottomLeft();
450*cdf0e10cSrcweir             eLocalKind = HDL_LWLFT;
451*cdf0e10cSrcweir             break;
452*cdf0e10cSrcweir 		case 8:
453*cdf0e10cSrcweir             aPnt = aRect.BottomCenter();
454*cdf0e10cSrcweir             eLocalKind = HDL_LOWER;
455*cdf0e10cSrcweir             break;
456*cdf0e10cSrcweir 		case 9:
457*cdf0e10cSrcweir             aPnt = aRect.BottomRight();
458*cdf0e10cSrcweir             eLocalKind = HDL_LWRGT;
459*cdf0e10cSrcweir             break;
460*cdf0e10cSrcweir 	}
461*cdf0e10cSrcweir 
462*cdf0e10cSrcweir     if (aGeo.nShearWink)
463*cdf0e10cSrcweir     {
464*cdf0e10cSrcweir         ShearPoint(aPnt,aRect.TopLeft(),aGeo.nTan);
465*cdf0e10cSrcweir     }
466*cdf0e10cSrcweir 
467*cdf0e10cSrcweir 	if (aGeo.nDrehWink)
468*cdf0e10cSrcweir     {
469*cdf0e10cSrcweir         RotatePoint(aPnt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
470*cdf0e10cSrcweir     }
471*cdf0e10cSrcweir 
472*cdf0e10cSrcweir 	if (eLocalKind != HDL_MOVE)
473*cdf0e10cSrcweir     {
474*cdf0e10cSrcweir 		pH = new SdrHdl(aPnt,eLocalKind);
475*cdf0e10cSrcweir 		pH->SetPointNum(nPNum);
476*cdf0e10cSrcweir 		pH->SetObj((SdrObject*)this);
477*cdf0e10cSrcweir 		pH->SetDrehWink(aGeo.nDrehWink);
478*cdf0e10cSrcweir 	}
479*cdf0e10cSrcweir 
480*cdf0e10cSrcweir     return pH;
481*cdf0e10cSrcweir }
482*cdf0e10cSrcweir 
483*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////////////////////////
484*cdf0e10cSrcweir 
485*cdf0e10cSrcweir bool SdrCircObj::hasSpecialDrag() const
486*cdf0e10cSrcweir {
487*cdf0e10cSrcweir 	return true;
488*cdf0e10cSrcweir }
489*cdf0e10cSrcweir 
490*cdf0e10cSrcweir bool SdrCircObj::beginSpecialDrag(SdrDragStat& rDrag) const
491*cdf0e10cSrcweir {
492*cdf0e10cSrcweir 	const bool bWink(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind());
493*cdf0e10cSrcweir 
494*cdf0e10cSrcweir 	if(bWink)
495*cdf0e10cSrcweir 	{
496*cdf0e10cSrcweir 		if(1 == rDrag.GetHdl()->GetPointNum() || 2 == rDrag.GetHdl()->GetPointNum())
497*cdf0e10cSrcweir 		{
498*cdf0e10cSrcweir 			rDrag.SetNoSnap(true);
499*cdf0e10cSrcweir 		}
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir 		return true;
502*cdf0e10cSrcweir 	}
503*cdf0e10cSrcweir 
504*cdf0e10cSrcweir     return SdrTextObj::beginSpecialDrag(rDrag);
505*cdf0e10cSrcweir }
506*cdf0e10cSrcweir 
507*cdf0e10cSrcweir bool SdrCircObj::applySpecialDrag(SdrDragStat& rDrag)
508*cdf0e10cSrcweir {
509*cdf0e10cSrcweir 	const bool bWink(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind());
510*cdf0e10cSrcweir 
511*cdf0e10cSrcweir 	if(bWink)
512*cdf0e10cSrcweir 	{
513*cdf0e10cSrcweir 		Point aPt(rDrag.GetNow());
514*cdf0e10cSrcweir 
515*cdf0e10cSrcweir         if (aGeo.nDrehWink!=0)
516*cdf0e10cSrcweir             RotatePoint(aPt,aRect.TopLeft(),-aGeo.nSin,aGeo.nCos);
517*cdf0e10cSrcweir 
518*cdf0e10cSrcweir         if (aGeo.nShearWink!=0)
519*cdf0e10cSrcweir             ShearPoint(aPt,aRect.TopLeft(),-aGeo.nTan);
520*cdf0e10cSrcweir 
521*cdf0e10cSrcweir         aPt-=aRect.Center();
522*cdf0e10cSrcweir 
523*cdf0e10cSrcweir         long nWdt=aRect.Right()-aRect.Left();
524*cdf0e10cSrcweir 		long nHgt=aRect.Bottom()-aRect.Top();
525*cdf0e10cSrcweir 
526*cdf0e10cSrcweir         if(nWdt>=nHgt)
527*cdf0e10cSrcweir         {
528*cdf0e10cSrcweir 			aPt.Y()=BigMulDiv(aPt.Y(),nWdt,nHgt);
529*cdf0e10cSrcweir 		}
530*cdf0e10cSrcweir         else
531*cdf0e10cSrcweir         {
532*cdf0e10cSrcweir 			aPt.X()=BigMulDiv(aPt.X(),nHgt,nWdt);
533*cdf0e10cSrcweir 		}
534*cdf0e10cSrcweir 
535*cdf0e10cSrcweir         long nWink=NormAngle360(GetAngle(aPt));
536*cdf0e10cSrcweir 
537*cdf0e10cSrcweir         if (rDrag.GetView() && rDrag.GetView()->IsAngleSnapEnabled())
538*cdf0e10cSrcweir         {
539*cdf0e10cSrcweir 			long nSA=rDrag.GetView()->GetSnapAngle();
540*cdf0e10cSrcweir 
541*cdf0e10cSrcweir             if (nSA!=0)
542*cdf0e10cSrcweir             {
543*cdf0e10cSrcweir 				nWink+=nSA/2;
544*cdf0e10cSrcweir 				nWink/=nSA;
545*cdf0e10cSrcweir 				nWink*=nSA;
546*cdf0e10cSrcweir 				nWink=NormAngle360(nWink);
547*cdf0e10cSrcweir 			}
548*cdf0e10cSrcweir 		}
549*cdf0e10cSrcweir 
550*cdf0e10cSrcweir 		if(1 == rDrag.GetHdl()->GetPointNum())
551*cdf0e10cSrcweir 		{
552*cdf0e10cSrcweir 			nStartWink = nWink;
553*cdf0e10cSrcweir 		}
554*cdf0e10cSrcweir 		else if(2 == rDrag.GetHdl()->GetPointNum())
555*cdf0e10cSrcweir 		{
556*cdf0e10cSrcweir 			nEndWink = nWink;
557*cdf0e10cSrcweir 		}
558*cdf0e10cSrcweir 
559*cdf0e10cSrcweir 		SetRectsDirty();
560*cdf0e10cSrcweir 		SetXPolyDirty();
561*cdf0e10cSrcweir 		ImpSetCircInfoToAttr();
562*cdf0e10cSrcweir 		SetChanged();
563*cdf0e10cSrcweir 
564*cdf0e10cSrcweir 		return true;
565*cdf0e10cSrcweir 	}
566*cdf0e10cSrcweir 	else
567*cdf0e10cSrcweir 	{
568*cdf0e10cSrcweir 		return SdrTextObj::applySpecialDrag(rDrag);
569*cdf0e10cSrcweir 	}
570*cdf0e10cSrcweir }
571*cdf0e10cSrcweir 
572*cdf0e10cSrcweir String SdrCircObj::getSpecialDragComment(const SdrDragStat& rDrag) const
573*cdf0e10cSrcweir {
574*cdf0e10cSrcweir     const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj());
575*cdf0e10cSrcweir 
576*cdf0e10cSrcweir     if(bCreateComment)
577*cdf0e10cSrcweir     {
578*cdf0e10cSrcweir 		XubString aStr;
579*cdf0e10cSrcweir 		ImpTakeDescriptionStr(STR_ViewCreateObj, aStr);
580*cdf0e10cSrcweir 		const sal_uInt32 nPntAnz(rDrag.GetPointAnz());
581*cdf0e10cSrcweir 
582*cdf0e10cSrcweir 		if(OBJ_CIRC != meCircleKind && nPntAnz > 2)
583*cdf0e10cSrcweir 		{
584*cdf0e10cSrcweir 			ImpCircUser* pU = (ImpCircUser*)rDrag.GetUser();
585*cdf0e10cSrcweir 			sal_Int32 nWink;
586*cdf0e10cSrcweir 
587*cdf0e10cSrcweir 			aStr.AppendAscii(" (");
588*cdf0e10cSrcweir 
589*cdf0e10cSrcweir 			if(3 == nPntAnz)
590*cdf0e10cSrcweir             {
591*cdf0e10cSrcweir 				nWink = pU->nStart;
592*cdf0e10cSrcweir             }
593*cdf0e10cSrcweir 			else
594*cdf0e10cSrcweir             {
595*cdf0e10cSrcweir 				nWink = pU->nEnd;
596*cdf0e10cSrcweir             }
597*cdf0e10cSrcweir 
598*cdf0e10cSrcweir 			aStr += GetWinkStr(nWink,sal_False);
599*cdf0e10cSrcweir 			aStr += sal_Unicode(')');
600*cdf0e10cSrcweir 		}
601*cdf0e10cSrcweir 
602*cdf0e10cSrcweir         return aStr;
603*cdf0e10cSrcweir     }
604*cdf0e10cSrcweir     else
605*cdf0e10cSrcweir     {
606*cdf0e10cSrcweir 	    const bool bWink(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind());
607*cdf0e10cSrcweir 
608*cdf0e10cSrcweir 	    if(bWink)
609*cdf0e10cSrcweir 	    {
610*cdf0e10cSrcweir 		    XubString aStr;
611*cdf0e10cSrcweir             const sal_Int32 nWink(1 == rDrag.GetHdl()->GetPointNum() ? nStartWink : nEndWink);
612*cdf0e10cSrcweir 
613*cdf0e10cSrcweir 		    ImpTakeDescriptionStr(STR_DragCircAngle, aStr);
614*cdf0e10cSrcweir 		    aStr.AppendAscii(" (");
615*cdf0e10cSrcweir 		    aStr += GetWinkStr(nWink,sal_False);
616*cdf0e10cSrcweir 		    aStr += sal_Unicode(')');
617*cdf0e10cSrcweir 
618*cdf0e10cSrcweir 		    return aStr;
619*cdf0e10cSrcweir 	    }
620*cdf0e10cSrcweir 	    else
621*cdf0e10cSrcweir 	    {
622*cdf0e10cSrcweir 		    return SdrTextObj::getSpecialDragComment(rDrag);
623*cdf0e10cSrcweir 	    }
624*cdf0e10cSrcweir     }
625*cdf0e10cSrcweir }
626*cdf0e10cSrcweir 
627*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////////////////////////
628*cdf0e10cSrcweir 
629*cdf0e10cSrcweir void ImpCircUser::SetCreateParams(SdrDragStat& rStat)
630*cdf0e10cSrcweir {
631*cdf0e10cSrcweir 	rStat.TakeCreateRect(aR);
632*cdf0e10cSrcweir 	aR.Justify();
633*cdf0e10cSrcweir 	aCenter=aR.Center();
634*cdf0e10cSrcweir 	nWdt=aR.Right()-aR.Left();
635*cdf0e10cSrcweir 	nHgt=aR.Bottom()-aR.Top();
636*cdf0e10cSrcweir 	nMaxRad=((nWdt>nHgt ? nWdt : nHgt)+1) /2;
637*cdf0e10cSrcweir 	nStart=0;
638*cdf0e10cSrcweir 	nEnd=36000;
639*cdf0e10cSrcweir 	if (rStat.GetPointAnz()>2) {
640*cdf0e10cSrcweir 		Point aP(rStat.GetPoint(2)-aCenter);
641*cdf0e10cSrcweir 		if (nWdt==0) aP.X()=0;
642*cdf0e10cSrcweir 		if (nHgt==0) aP.Y()=0;
643*cdf0e10cSrcweir 		if (nWdt>=nHgt) {
644*cdf0e10cSrcweir 			if (nHgt!=0) aP.Y()=aP.Y()*nWdt/nHgt;
645*cdf0e10cSrcweir 		} else {
646*cdf0e10cSrcweir 			if (nWdt!=0) aP.X()=aP.X()*nHgt/nWdt;
647*cdf0e10cSrcweir 		}
648*cdf0e10cSrcweir 		nStart=NormAngle360(GetAngle(aP));
649*cdf0e10cSrcweir 		if (rStat.GetView()!=NULL && rStat.GetView()->IsAngleSnapEnabled()) {
650*cdf0e10cSrcweir 			long nSA=rStat.GetView()->GetSnapAngle();
651*cdf0e10cSrcweir 			if (nSA!=0) { // Winkelfang
652*cdf0e10cSrcweir 				nStart+=nSA/2;
653*cdf0e10cSrcweir 				nStart/=nSA;
654*cdf0e10cSrcweir 				nStart*=nSA;
655*cdf0e10cSrcweir 				nStart=NormAngle360(nStart);
656*cdf0e10cSrcweir 			}
657*cdf0e10cSrcweir 		}
658*cdf0e10cSrcweir 		aP1 = GetWinkPnt(aR,nStart);
659*cdf0e10cSrcweir 		nEnd=nStart;
660*cdf0e10cSrcweir 		aP2=aP1;
661*cdf0e10cSrcweir 	} else aP1=aCenter;
662*cdf0e10cSrcweir 	if (rStat.GetPointAnz()>3) {
663*cdf0e10cSrcweir 		Point aP(rStat.GetPoint(3)-aCenter);
664*cdf0e10cSrcweir 		if (nWdt>=nHgt) {
665*cdf0e10cSrcweir 			aP.Y()=BigMulDiv(aP.Y(),nWdt,nHgt);
666*cdf0e10cSrcweir 		} else {
667*cdf0e10cSrcweir 			aP.X()=BigMulDiv(aP.X(),nHgt,nWdt);
668*cdf0e10cSrcweir 		}
669*cdf0e10cSrcweir 		nEnd=NormAngle360(GetAngle(aP));
670*cdf0e10cSrcweir 		if (rStat.GetView()!=NULL && rStat.GetView()->IsAngleSnapEnabled()) {
671*cdf0e10cSrcweir 			long nSA=rStat.GetView()->GetSnapAngle();
672*cdf0e10cSrcweir 			if (nSA!=0) { // Winkelfang
673*cdf0e10cSrcweir 				nEnd+=nSA/2;
674*cdf0e10cSrcweir 				nEnd/=nSA;
675*cdf0e10cSrcweir 				nEnd*=nSA;
676*cdf0e10cSrcweir 				nEnd=NormAngle360(nEnd);
677*cdf0e10cSrcweir 			}
678*cdf0e10cSrcweir 		}
679*cdf0e10cSrcweir 		aP2 = GetWinkPnt(aR,nEnd);
680*cdf0e10cSrcweir 	} else aP2=aCenter;
681*cdf0e10cSrcweir }
682*cdf0e10cSrcweir 
683*cdf0e10cSrcweir void SdrCircObj::ImpSetCreateParams(SdrDragStat& rStat) const
684*cdf0e10cSrcweir {
685*cdf0e10cSrcweir 	ImpCircUser* pU=(ImpCircUser*)rStat.GetUser();
686*cdf0e10cSrcweir 	if (pU==NULL) {
687*cdf0e10cSrcweir 		pU=new ImpCircUser;
688*cdf0e10cSrcweir 		rStat.SetUser(pU);
689*cdf0e10cSrcweir 	}
690*cdf0e10cSrcweir 	pU->SetCreateParams(rStat);
691*cdf0e10cSrcweir }
692*cdf0e10cSrcweir 
693*cdf0e10cSrcweir FASTBOOL SdrCircObj::BegCreate(SdrDragStat& rStat)
694*cdf0e10cSrcweir {
695*cdf0e10cSrcweir 	rStat.SetOrtho4Possible();
696*cdf0e10cSrcweir 	Rectangle aRect1(rStat.GetStart(), rStat.GetNow());
697*cdf0e10cSrcweir 	aRect1.Justify();
698*cdf0e10cSrcweir 	rStat.SetActionRect(aRect1);
699*cdf0e10cSrcweir 	aRect = aRect1;
700*cdf0e10cSrcweir 	ImpSetCreateParams(rStat);
701*cdf0e10cSrcweir 	return sal_True;
702*cdf0e10cSrcweir }
703*cdf0e10cSrcweir 
704*cdf0e10cSrcweir FASTBOOL SdrCircObj::MovCreate(SdrDragStat& rStat)
705*cdf0e10cSrcweir {
706*cdf0e10cSrcweir 	ImpSetCreateParams(rStat);
707*cdf0e10cSrcweir 	ImpCircUser* pU=(ImpCircUser*)rStat.GetUser();
708*cdf0e10cSrcweir 	rStat.SetActionRect(pU->aR);
709*cdf0e10cSrcweir 	aRect=pU->aR; // fuer ObjName
710*cdf0e10cSrcweir 	ImpJustifyRect(aRect);
711*cdf0e10cSrcweir 	nStartWink=pU->nStart;
712*cdf0e10cSrcweir 	nEndWink=pU->nEnd;
713*cdf0e10cSrcweir 	SetBoundRectDirty();
714*cdf0e10cSrcweir 	bSnapRectDirty=sal_True;
715*cdf0e10cSrcweir 	SetXPolyDirty();
716*cdf0e10cSrcweir 
717*cdf0e10cSrcweir     // #i103058# push current angle settings to ItemSet to
718*cdf0e10cSrcweir     // allow FullDrag visualisation
719*cdf0e10cSrcweir     if(rStat.GetPointAnz() >= 4)
720*cdf0e10cSrcweir     {
721*cdf0e10cSrcweir         ImpSetCircInfoToAttr();
722*cdf0e10cSrcweir     }
723*cdf0e10cSrcweir 
724*cdf0e10cSrcweir 	return sal_True;
725*cdf0e10cSrcweir }
726*cdf0e10cSrcweir 
727*cdf0e10cSrcweir FASTBOOL SdrCircObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
728*cdf0e10cSrcweir {
729*cdf0e10cSrcweir 	ImpSetCreateParams(rStat);
730*cdf0e10cSrcweir 	ImpCircUser* pU=(ImpCircUser*)rStat.GetUser();
731*cdf0e10cSrcweir 	FASTBOOL bRet=sal_False;
732*cdf0e10cSrcweir 	if (eCmd==SDRCREATE_FORCEEND && rStat.GetPointAnz()<4) meCircleKind=OBJ_CIRC;
733*cdf0e10cSrcweir 	if (meCircleKind==OBJ_CIRC) {
734*cdf0e10cSrcweir 		bRet=rStat.GetPointAnz()>=2;
735*cdf0e10cSrcweir 		if (bRet) {
736*cdf0e10cSrcweir 			aRect=pU->aR;
737*cdf0e10cSrcweir 			ImpJustifyRect(aRect);
738*cdf0e10cSrcweir 		}
739*cdf0e10cSrcweir 	} else {
740*cdf0e10cSrcweir 		rStat.SetNoSnap(rStat.GetPointAnz()>=2);
741*cdf0e10cSrcweir 		rStat.SetOrtho4Possible(rStat.GetPointAnz()<2);
742*cdf0e10cSrcweir 		bRet=rStat.GetPointAnz()>=4;
743*cdf0e10cSrcweir 		if (bRet) {
744*cdf0e10cSrcweir 			aRect=pU->aR;
745*cdf0e10cSrcweir 			ImpJustifyRect(aRect);
746*cdf0e10cSrcweir 			nStartWink=pU->nStart;
747*cdf0e10cSrcweir 			nEndWink=pU->nEnd;
748*cdf0e10cSrcweir 		}
749*cdf0e10cSrcweir 	}
750*cdf0e10cSrcweir 	bClosedObj=meCircleKind!=OBJ_CARC;
751*cdf0e10cSrcweir 	SetRectsDirty();
752*cdf0e10cSrcweir 	SetXPolyDirty();
753*cdf0e10cSrcweir 	ImpSetCircInfoToAttr();
754*cdf0e10cSrcweir 	if (bRet) {
755*cdf0e10cSrcweir 		delete pU;
756*cdf0e10cSrcweir 		rStat.SetUser(NULL);
757*cdf0e10cSrcweir 	}
758*cdf0e10cSrcweir 	return bRet;
759*cdf0e10cSrcweir }
760*cdf0e10cSrcweir 
761*cdf0e10cSrcweir void SdrCircObj::BrkCreate(SdrDragStat& rStat)
762*cdf0e10cSrcweir {
763*cdf0e10cSrcweir 	ImpCircUser* pU=(ImpCircUser*)rStat.GetUser();
764*cdf0e10cSrcweir 	delete pU;
765*cdf0e10cSrcweir 	rStat.SetUser(NULL);
766*cdf0e10cSrcweir }
767*cdf0e10cSrcweir 
768*cdf0e10cSrcweir FASTBOOL SdrCircObj::BckCreate(SdrDragStat& rStat)
769*cdf0e10cSrcweir {
770*cdf0e10cSrcweir 	rStat.SetNoSnap(rStat.GetPointAnz()>=3);
771*cdf0e10cSrcweir 	rStat.SetOrtho4Possible(rStat.GetPointAnz()<3);
772*cdf0e10cSrcweir 	return meCircleKind!=OBJ_CIRC;
773*cdf0e10cSrcweir }
774*cdf0e10cSrcweir 
775*cdf0e10cSrcweir basegfx::B2DPolyPolygon SdrCircObj::TakeCreatePoly(const SdrDragStat& rDrag) const
776*cdf0e10cSrcweir {
777*cdf0e10cSrcweir 	ImpCircUser* pU = (ImpCircUser*)rDrag.GetUser();
778*cdf0e10cSrcweir 
779*cdf0e10cSrcweir 	if(rDrag.GetPointAnz() < 4L)
780*cdf0e10cSrcweir 	{
781*cdf0e10cSrcweir 		// force to OBJ_CIRC to get full visualisation
782*cdf0e10cSrcweir 		basegfx::B2DPolyPolygon aRetval(ImpCalcXPolyCirc(OBJ_CIRC, pU->aR, pU->nStart, pU->nEnd));
783*cdf0e10cSrcweir 
784*cdf0e10cSrcweir 		if(3L == rDrag.GetPointAnz())
785*cdf0e10cSrcweir 		{
786*cdf0e10cSrcweir 			// add edge to first point on ellipse
787*cdf0e10cSrcweir 			basegfx::B2DPolygon aNew;
788*cdf0e10cSrcweir 
789*cdf0e10cSrcweir 			aNew.append(basegfx::B2DPoint(pU->aCenter.X(), pU->aCenter.Y()));
790*cdf0e10cSrcweir 			aNew.append(basegfx::B2DPoint(pU->aP1.X(), pU->aP1.Y()));
791*cdf0e10cSrcweir 			aRetval.append(aNew);
792*cdf0e10cSrcweir 		}
793*cdf0e10cSrcweir 
794*cdf0e10cSrcweir 		return aRetval;
795*cdf0e10cSrcweir 	}
796*cdf0e10cSrcweir 	else
797*cdf0e10cSrcweir 	{
798*cdf0e10cSrcweir 		return basegfx::B2DPolyPolygon(ImpCalcXPolyCirc(meCircleKind, pU->aR, pU->nStart, pU->nEnd));
799*cdf0e10cSrcweir 	}
800*cdf0e10cSrcweir }
801*cdf0e10cSrcweir 
802*cdf0e10cSrcweir Pointer SdrCircObj::GetCreatePointer() const
803*cdf0e10cSrcweir {
804*cdf0e10cSrcweir 	switch (meCircleKind) {
805*cdf0e10cSrcweir 		case OBJ_CIRC: return Pointer(POINTER_DRAW_ELLIPSE);
806*cdf0e10cSrcweir 		case OBJ_SECT: return Pointer(POINTER_DRAW_PIE);
807*cdf0e10cSrcweir 		case OBJ_CARC: return Pointer(POINTER_DRAW_ARC);
808*cdf0e10cSrcweir 		case OBJ_CCUT: return Pointer(POINTER_DRAW_CIRCLECUT);
809*cdf0e10cSrcweir 		default: break;
810*cdf0e10cSrcweir 	} // switch
811*cdf0e10cSrcweir 	return Pointer(POINTER_CROSS);
812*cdf0e10cSrcweir }
813*cdf0e10cSrcweir 
814*cdf0e10cSrcweir void SdrCircObj::NbcMove(const Size& aSiz)
815*cdf0e10cSrcweir {
816*cdf0e10cSrcweir 	MoveRect(aRect,aSiz);
817*cdf0e10cSrcweir 	MoveRect(aOutRect,aSiz);
818*cdf0e10cSrcweir 	MoveRect(maSnapRect,aSiz);
819*cdf0e10cSrcweir 	SetXPolyDirty();
820*cdf0e10cSrcweir 	SetRectsDirty(sal_True);
821*cdf0e10cSrcweir }
822*cdf0e10cSrcweir 
823*cdf0e10cSrcweir void SdrCircObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
824*cdf0e10cSrcweir {
825*cdf0e10cSrcweir 	long nWink0=aGeo.nDrehWink;
826*cdf0e10cSrcweir 	FASTBOOL bNoShearRota=(aGeo.nDrehWink==0 && aGeo.nShearWink==0);
827*cdf0e10cSrcweir 	SdrTextObj::NbcResize(rRef,xFact,yFact);
828*cdf0e10cSrcweir 	bNoShearRota|=(aGeo.nDrehWink==0 && aGeo.nShearWink==0);
829*cdf0e10cSrcweir 	if (meCircleKind!=OBJ_CIRC) {
830*cdf0e10cSrcweir 		FASTBOOL bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0);
831*cdf0e10cSrcweir 		FASTBOOL bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0);
832*cdf0e10cSrcweir 		if (bXMirr || bYMirr) {
833*cdf0e10cSrcweir 			// bei bXMirr!=bYMirr muessten eigentlich noch die beiden
834*cdf0e10cSrcweir 			// Linienende vertauscht werden. Das ist jedoch mal wieder
835*cdf0e10cSrcweir 			// schlecht (wg. zwangslaeufiger harter Formatierung).
836*cdf0e10cSrcweir 			// Alternativ koennte ein bMirrored-Flag eingefuehrt werden
837*cdf0e10cSrcweir 			// (Vielleicht ja mal grundsaetzlich, auch fuer gepiegelten Text, ...).
838*cdf0e10cSrcweir 			long nS0=nStartWink;
839*cdf0e10cSrcweir 			long nE0=nEndWink;
840*cdf0e10cSrcweir 			if (bNoShearRota) {
841*cdf0e10cSrcweir 				// Das RectObj spiegelt bei VMirror bereits durch durch 180deg Drehung.
842*cdf0e10cSrcweir 				if (! (bXMirr && bYMirr)) {
843*cdf0e10cSrcweir 					long nTmp=nS0;
844*cdf0e10cSrcweir 					nS0=18000-nE0;
845*cdf0e10cSrcweir 					nE0=18000-nTmp;
846*cdf0e10cSrcweir 				}
847*cdf0e10cSrcweir 			} else { // Spiegeln fuer verzerrte Ellipsen
848*cdf0e10cSrcweir 				if (bXMirr!=bYMirr) {
849*cdf0e10cSrcweir 					nS0+=nWink0;
850*cdf0e10cSrcweir 					nE0+=nWink0;
851*cdf0e10cSrcweir 					if (bXMirr) {
852*cdf0e10cSrcweir 						long nTmp=nS0;
853*cdf0e10cSrcweir 						nS0=18000-nE0;
854*cdf0e10cSrcweir 						nE0=18000-nTmp;
855*cdf0e10cSrcweir 					}
856*cdf0e10cSrcweir 					if (bYMirr) {
857*cdf0e10cSrcweir 						long nTmp=nS0;
858*cdf0e10cSrcweir 						nS0=-nE0;
859*cdf0e10cSrcweir 						nE0=-nTmp;
860*cdf0e10cSrcweir 					}
861*cdf0e10cSrcweir 					nS0-=aGeo.nDrehWink;
862*cdf0e10cSrcweir 					nE0-=aGeo.nDrehWink;
863*cdf0e10cSrcweir 				}
864*cdf0e10cSrcweir 			}
865*cdf0e10cSrcweir 			long nWinkDif=nE0-nS0;
866*cdf0e10cSrcweir 			nStartWink=NormAngle360(nS0);
867*cdf0e10cSrcweir 			nEndWink  =NormAngle360(nE0);
868*cdf0e10cSrcweir 			if (nWinkDif==36000) nEndWink+=nWinkDif; // Vollkreis
869*cdf0e10cSrcweir 		}
870*cdf0e10cSrcweir 	}
871*cdf0e10cSrcweir 	SetXPolyDirty();
872*cdf0e10cSrcweir 	ImpSetCircInfoToAttr();
873*cdf0e10cSrcweir }
874*cdf0e10cSrcweir 
875*cdf0e10cSrcweir void SdrCircObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
876*cdf0e10cSrcweir {
877*cdf0e10cSrcweir 	SdrTextObj::NbcShear(rRef,nWink,tn,bVShear);
878*cdf0e10cSrcweir 	SetXPolyDirty();
879*cdf0e10cSrcweir 	ImpSetCircInfoToAttr();
880*cdf0e10cSrcweir }
881*cdf0e10cSrcweir 
882*cdf0e10cSrcweir void SdrCircObj::NbcMirror(const Point& rRef1, const Point& rRef2)
883*cdf0e10cSrcweir {
884*cdf0e10cSrcweir 	//long nWink0=aGeo.nDrehWink;
885*cdf0e10cSrcweir 	FASTBOOL bFreeMirr=meCircleKind!=OBJ_CIRC;
886*cdf0e10cSrcweir 	Point aTmpPt1;
887*cdf0e10cSrcweir 	Point aTmpPt2;
888*cdf0e10cSrcweir 	if (bFreeMirr) { // bei freier Spiegelachse einige Vorbereitungen Treffen
889*cdf0e10cSrcweir 		Point aCenter(aRect.Center());
890*cdf0e10cSrcweir 		long nWdt=aRect.GetWidth()-1;
891*cdf0e10cSrcweir 		long nHgt=aRect.GetHeight()-1;
892*cdf0e10cSrcweir 		long nMaxRad=((nWdt>nHgt ? nWdt : nHgt)+1) /2;
893*cdf0e10cSrcweir 		double a;
894*cdf0e10cSrcweir 		// Startpunkt
895*cdf0e10cSrcweir 		a=nStartWink*nPi180;
896*cdf0e10cSrcweir 		aTmpPt1=Point(Round(cos(a)*nMaxRad),-Round(sin(a)*nMaxRad));
897*cdf0e10cSrcweir 		if (nWdt==0) aTmpPt1.X()=0;
898*cdf0e10cSrcweir 		if (nHgt==0) aTmpPt1.Y()=0;
899*cdf0e10cSrcweir 		aTmpPt1+=aCenter;
900*cdf0e10cSrcweir 		// Endpunkt
901*cdf0e10cSrcweir 		a=nEndWink*nPi180;
902*cdf0e10cSrcweir 		aTmpPt2=Point(Round(cos(a)*nMaxRad),-Round(sin(a)*nMaxRad));
903*cdf0e10cSrcweir 		if (nWdt==0) aTmpPt2.X()=0;
904*cdf0e10cSrcweir 		if (nHgt==0) aTmpPt2.Y()=0;
905*cdf0e10cSrcweir 		aTmpPt2+=aCenter;
906*cdf0e10cSrcweir 		if (aGeo.nDrehWink!=0) {
907*cdf0e10cSrcweir 			RotatePoint(aTmpPt1,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
908*cdf0e10cSrcweir 			RotatePoint(aTmpPt2,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
909*cdf0e10cSrcweir 		}
910*cdf0e10cSrcweir 		if (aGeo.nShearWink!=0) {
911*cdf0e10cSrcweir 			ShearPoint(aTmpPt1,aRect.TopLeft(),aGeo.nTan);
912*cdf0e10cSrcweir 			ShearPoint(aTmpPt2,aRect.TopLeft(),aGeo.nTan);
913*cdf0e10cSrcweir 		}
914*cdf0e10cSrcweir 	}
915*cdf0e10cSrcweir 	SdrTextObj::NbcMirror(rRef1,rRef2);
916*cdf0e10cSrcweir 	if (meCircleKind!=OBJ_CIRC) { // Anpassung von Start- und Endwinkel
917*cdf0e10cSrcweir 		MirrorPoint(aTmpPt1,rRef1,rRef2);
918*cdf0e10cSrcweir 		MirrorPoint(aTmpPt2,rRef1,rRef2);
919*cdf0e10cSrcweir 		// Unrotate:
920*cdf0e10cSrcweir 		if (aGeo.nDrehWink!=0) {
921*cdf0e10cSrcweir 			RotatePoint(aTmpPt1,aRect.TopLeft(),-aGeo.nSin,aGeo.nCos); // -sin fuer Umkehrung
922*cdf0e10cSrcweir 			RotatePoint(aTmpPt2,aRect.TopLeft(),-aGeo.nSin,aGeo.nCos); // -sin fuer Umkehrung
923*cdf0e10cSrcweir 		}
924*cdf0e10cSrcweir 		// Unshear:
925*cdf0e10cSrcweir 		if (aGeo.nShearWink!=0) {
926*cdf0e10cSrcweir 			ShearPoint(aTmpPt1,aRect.TopLeft(),-aGeo.nTan); // -tan fuer Umkehrung
927*cdf0e10cSrcweir 			ShearPoint(aTmpPt2,aRect.TopLeft(),-aGeo.nTan); // -tan fuer Umkehrung
928*cdf0e10cSrcweir 		}
929*cdf0e10cSrcweir 		Point aCenter(aRect.Center());
930*cdf0e10cSrcweir 		aTmpPt1-=aCenter;
931*cdf0e10cSrcweir 		aTmpPt2-=aCenter;
932*cdf0e10cSrcweir 		// Weil gespiegelt sind die Winkel nun auch noch vertauscht
933*cdf0e10cSrcweir 		nStartWink=GetAngle(aTmpPt2);
934*cdf0e10cSrcweir 		nEndWink  =GetAngle(aTmpPt1);
935*cdf0e10cSrcweir 		long nWinkDif=nEndWink-nStartWink;
936*cdf0e10cSrcweir 		nStartWink=NormAngle360(nStartWink);
937*cdf0e10cSrcweir 		nEndWink  =NormAngle360(nEndWink);
938*cdf0e10cSrcweir 		if (nWinkDif==36000) nEndWink+=nWinkDif; // Vollkreis
939*cdf0e10cSrcweir 	}
940*cdf0e10cSrcweir 	SetXPolyDirty();
941*cdf0e10cSrcweir 	ImpSetCircInfoToAttr();
942*cdf0e10cSrcweir }
943*cdf0e10cSrcweir 
944*cdf0e10cSrcweir SdrObjGeoData* SdrCircObj::NewGeoData() const
945*cdf0e10cSrcweir {
946*cdf0e10cSrcweir 	return new SdrCircObjGeoData;
947*cdf0e10cSrcweir }
948*cdf0e10cSrcweir 
949*cdf0e10cSrcweir void SdrCircObj::SaveGeoData(SdrObjGeoData& rGeo) const
950*cdf0e10cSrcweir {
951*cdf0e10cSrcweir 	SdrRectObj::SaveGeoData(rGeo);
952*cdf0e10cSrcweir 	SdrCircObjGeoData& rCGeo=(SdrCircObjGeoData&)rGeo;
953*cdf0e10cSrcweir 	rCGeo.nStartWink=nStartWink;
954*cdf0e10cSrcweir 	rCGeo.nEndWink  =nEndWink;
955*cdf0e10cSrcweir }
956*cdf0e10cSrcweir 
957*cdf0e10cSrcweir void SdrCircObj::RestGeoData(const SdrObjGeoData& rGeo)
958*cdf0e10cSrcweir {
959*cdf0e10cSrcweir 	SdrRectObj::RestGeoData(rGeo);
960*cdf0e10cSrcweir 	SdrCircObjGeoData& rCGeo=(SdrCircObjGeoData&)rGeo;
961*cdf0e10cSrcweir 	nStartWink=rCGeo.nStartWink;
962*cdf0e10cSrcweir 	nEndWink  =rCGeo.nEndWink;
963*cdf0e10cSrcweir 	SetXPolyDirty();
964*cdf0e10cSrcweir 	ImpSetCircInfoToAttr();
965*cdf0e10cSrcweir }
966*cdf0e10cSrcweir 
967*cdf0e10cSrcweir void Union(Rectangle& rR, const Point& rP)
968*cdf0e10cSrcweir {
969*cdf0e10cSrcweir 	if (rP.X()<rR.Left  ()) rR.Left  ()=rP.X();
970*cdf0e10cSrcweir 	if (rP.X()>rR.Right ()) rR.Right ()=rP.X();
971*cdf0e10cSrcweir 	if (rP.Y()<rR.Top   ()) rR.Top   ()=rP.Y();
972*cdf0e10cSrcweir 	if (rP.Y()>rR.Bottom()) rR.Bottom()=rP.Y();
973*cdf0e10cSrcweir }
974*cdf0e10cSrcweir 
975*cdf0e10cSrcweir void SdrCircObj::TakeUnrotatedSnapRect(Rectangle& rRect) const
976*cdf0e10cSrcweir {
977*cdf0e10cSrcweir 	rRect=aRect;
978*cdf0e10cSrcweir 	if (meCircleKind!=OBJ_CIRC) {
979*cdf0e10cSrcweir 		const Point aPntStart(GetWinkPnt(aRect,nStartWink));
980*cdf0e10cSrcweir 		const Point aPntEnd(GetWinkPnt(aRect,nEndWink));
981*cdf0e10cSrcweir 		long a=nStartWink;
982*cdf0e10cSrcweir 		long e=nEndWink;
983*cdf0e10cSrcweir 		rRect.Left  ()=aRect.Right();
984*cdf0e10cSrcweir 		rRect.Right ()=aRect.Left();
985*cdf0e10cSrcweir 		rRect.Top   ()=aRect.Bottom();
986*cdf0e10cSrcweir 		rRect.Bottom()=aRect.Top();
987*cdf0e10cSrcweir 		Union(rRect,aPntStart);
988*cdf0e10cSrcweir 		Union(rRect,aPntEnd);
989*cdf0e10cSrcweir 		if ((a<=18000 && e>=18000) || (a>e && (a<=18000 || e>=18000))) {
990*cdf0e10cSrcweir 			Union(rRect,aRect.LeftCenter());
991*cdf0e10cSrcweir 		}
992*cdf0e10cSrcweir 		if ((a<=27000 && e>=27000) || (a>e && (a<=27000 || e>=27000))) {
993*cdf0e10cSrcweir 			Union(rRect,aRect.BottomCenter());
994*cdf0e10cSrcweir 		}
995*cdf0e10cSrcweir 		if (a>e) {
996*cdf0e10cSrcweir 			Union(rRect,aRect.RightCenter());
997*cdf0e10cSrcweir 		}
998*cdf0e10cSrcweir 		if ((a<=9000 && e>=9000) || (a>e && (a<=9000 || e>=9000))) {
999*cdf0e10cSrcweir 			Union(rRect,aRect.TopCenter());
1000*cdf0e10cSrcweir 		}
1001*cdf0e10cSrcweir 		if (meCircleKind==OBJ_SECT) {
1002*cdf0e10cSrcweir 			Union(rRect,aRect.Center());
1003*cdf0e10cSrcweir 		}
1004*cdf0e10cSrcweir 		if (aGeo.nDrehWink!=0) {
1005*cdf0e10cSrcweir 			Point aDst(rRect.TopLeft());
1006*cdf0e10cSrcweir 			aDst-=aRect.TopLeft();
1007*cdf0e10cSrcweir 			Point aDst0(aDst);
1008*cdf0e10cSrcweir 			RotatePoint(aDst,Point(),aGeo.nSin,aGeo.nCos);
1009*cdf0e10cSrcweir 			aDst-=aDst0;
1010*cdf0e10cSrcweir 			rRect.Move(aDst.X(),aDst.Y());
1011*cdf0e10cSrcweir 		}
1012*cdf0e10cSrcweir 	}
1013*cdf0e10cSrcweir 	if (aGeo.nShearWink!=0) {
1014*cdf0e10cSrcweir 		long nDst=Round((rRect.Bottom()-rRect.Top())*aGeo.nTan);
1015*cdf0e10cSrcweir 		if (aGeo.nShearWink>0) {
1016*cdf0e10cSrcweir 			Point aRef(rRect.TopLeft());
1017*cdf0e10cSrcweir 			rRect.Left()-=nDst;
1018*cdf0e10cSrcweir 			Point aTmpPt(rRect.TopLeft());
1019*cdf0e10cSrcweir 			RotatePoint(aTmpPt,aRef,aGeo.nSin,aGeo.nCos);
1020*cdf0e10cSrcweir 			aTmpPt-=rRect.TopLeft();
1021*cdf0e10cSrcweir 			rRect.Move(aTmpPt.X(),aTmpPt.Y());
1022*cdf0e10cSrcweir 		} else {
1023*cdf0e10cSrcweir 			rRect.Right()-=nDst;
1024*cdf0e10cSrcweir 		}
1025*cdf0e10cSrcweir 	}
1026*cdf0e10cSrcweir }
1027*cdf0e10cSrcweir 
1028*cdf0e10cSrcweir void SdrCircObj::RecalcSnapRect()
1029*cdf0e10cSrcweir {
1030*cdf0e10cSrcweir 	if (PaintNeedsXPolyCirc()) {
1031*cdf0e10cSrcweir 		maSnapRect=GetXPoly().GetBoundRect();
1032*cdf0e10cSrcweir 	} else {
1033*cdf0e10cSrcweir 		TakeUnrotatedSnapRect(maSnapRect);
1034*cdf0e10cSrcweir 	}
1035*cdf0e10cSrcweir }
1036*cdf0e10cSrcweir 
1037*cdf0e10cSrcweir void SdrCircObj::NbcSetSnapRect(const Rectangle& rRect)
1038*cdf0e10cSrcweir {
1039*cdf0e10cSrcweir 	if (aGeo.nDrehWink!=0 || aGeo.nShearWink!=0 || meCircleKind!=OBJ_CIRC) {
1040*cdf0e10cSrcweir 		Rectangle aSR0(GetSnapRect());
1041*cdf0e10cSrcweir 		long nWdt0=aSR0.Right()-aSR0.Left();
1042*cdf0e10cSrcweir 		long nHgt0=aSR0.Bottom()-aSR0.Top();
1043*cdf0e10cSrcweir 		long nWdt1=rRect.Right()-rRect.Left();
1044*cdf0e10cSrcweir 		long nHgt1=rRect.Bottom()-rRect.Top();
1045*cdf0e10cSrcweir 		NbcResize(maSnapRect.TopLeft(),Fraction(nWdt1,nWdt0),Fraction(nHgt1,nHgt0));
1046*cdf0e10cSrcweir 		NbcMove(Size(rRect.Left()-aSR0.Left(),rRect.Top()-aSR0.Top()));
1047*cdf0e10cSrcweir 	} else {
1048*cdf0e10cSrcweir 		aRect=rRect;
1049*cdf0e10cSrcweir 		ImpJustifyRect(aRect);
1050*cdf0e10cSrcweir 	}
1051*cdf0e10cSrcweir 	SetRectsDirty();
1052*cdf0e10cSrcweir 	SetXPolyDirty();
1053*cdf0e10cSrcweir 	ImpSetCircInfoToAttr();
1054*cdf0e10cSrcweir }
1055*cdf0e10cSrcweir 
1056*cdf0e10cSrcweir sal_uInt32 SdrCircObj::GetSnapPointCount() const
1057*cdf0e10cSrcweir {
1058*cdf0e10cSrcweir 	if (meCircleKind==OBJ_CIRC) {
1059*cdf0e10cSrcweir 		return 1L;
1060*cdf0e10cSrcweir 	} else {
1061*cdf0e10cSrcweir 		return 3L;
1062*cdf0e10cSrcweir 	}
1063*cdf0e10cSrcweir }
1064*cdf0e10cSrcweir 
1065*cdf0e10cSrcweir Point SdrCircObj::GetSnapPoint(sal_uInt32 i) const
1066*cdf0e10cSrcweir {
1067*cdf0e10cSrcweir 	switch (i) {
1068*cdf0e10cSrcweir 		case 1 : return GetWinkPnt(aRect,nStartWink);
1069*cdf0e10cSrcweir 		case 2 : return GetWinkPnt(aRect,nEndWink);
1070*cdf0e10cSrcweir 		default: return aRect.Center();
1071*cdf0e10cSrcweir 	}
1072*cdf0e10cSrcweir }
1073*cdf0e10cSrcweir 
1074*cdf0e10cSrcweir void __EXPORT SdrCircObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
1075*cdf0e10cSrcweir {
1076*cdf0e10cSrcweir 	SetXPolyDirty();
1077*cdf0e10cSrcweir 	SdrRectObj::Notify(rBC,rHint);
1078*cdf0e10cSrcweir 	ImpSetAttrToCircInfo();
1079*cdf0e10cSrcweir }
1080*cdf0e10cSrcweir 
1081*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////////////////////////
1082*cdf0e10cSrcweir 
1083*cdf0e10cSrcweir void SdrCircObj::ImpSetAttrToCircInfo()
1084*cdf0e10cSrcweir {
1085*cdf0e10cSrcweir 	const SfxItemSet& rSet = GetObjectItemSet();
1086*cdf0e10cSrcweir 	SdrCircKind eNewKindA = ((SdrCircKindItem&)rSet.Get(SDRATTR_CIRCKIND)).GetValue();
1087*cdf0e10cSrcweir 	SdrObjKind eNewKind = meCircleKind;
1088*cdf0e10cSrcweir 
1089*cdf0e10cSrcweir 	if(eNewKindA == SDRCIRC_FULL)
1090*cdf0e10cSrcweir 		eNewKind = OBJ_CIRC;
1091*cdf0e10cSrcweir 	else if(eNewKindA == SDRCIRC_SECT)
1092*cdf0e10cSrcweir 		eNewKind = OBJ_SECT;
1093*cdf0e10cSrcweir 	else if(eNewKindA == SDRCIRC_ARC)
1094*cdf0e10cSrcweir 		eNewKind = OBJ_CARC;
1095*cdf0e10cSrcweir 	else if(eNewKindA == SDRCIRC_CUT)
1096*cdf0e10cSrcweir 		eNewKind = OBJ_CCUT;
1097*cdf0e10cSrcweir 
1098*cdf0e10cSrcweir 	sal_Int32 nNewStart = ((SdrCircStartAngleItem&)rSet.Get(SDRATTR_CIRCSTARTANGLE)).GetValue();
1099*cdf0e10cSrcweir 	sal_Int32 nNewEnd = ((SdrCircEndAngleItem&)rSet.Get(SDRATTR_CIRCENDANGLE)).GetValue();
1100*cdf0e10cSrcweir 
1101*cdf0e10cSrcweir 	sal_Bool bKindChg = meCircleKind != eNewKind;
1102*cdf0e10cSrcweir 	sal_Bool bWinkChg = nNewStart != nStartWink || nNewEnd != nEndWink;
1103*cdf0e10cSrcweir 
1104*cdf0e10cSrcweir 	if(bKindChg || bWinkChg)
1105*cdf0e10cSrcweir 	{
1106*cdf0e10cSrcweir 		meCircleKind = eNewKind;
1107*cdf0e10cSrcweir 		nStartWink = nNewStart;
1108*cdf0e10cSrcweir 		nEndWink = nNewEnd;
1109*cdf0e10cSrcweir 
1110*cdf0e10cSrcweir 		if(bKindChg || (meCircleKind != OBJ_CIRC && bWinkChg))
1111*cdf0e10cSrcweir 		{
1112*cdf0e10cSrcweir 			SetXPolyDirty();
1113*cdf0e10cSrcweir 			SetRectsDirty();
1114*cdf0e10cSrcweir 		}
1115*cdf0e10cSrcweir 	}
1116*cdf0e10cSrcweir }
1117*cdf0e10cSrcweir 
1118*cdf0e10cSrcweir void SdrCircObj::ImpSetCircInfoToAttr()
1119*cdf0e10cSrcweir {
1120*cdf0e10cSrcweir 	SdrCircKind eNewKindA = SDRCIRC_FULL;
1121*cdf0e10cSrcweir 	const SfxItemSet& rSet = GetObjectItemSet();
1122*cdf0e10cSrcweir 
1123*cdf0e10cSrcweir 	if(meCircleKind == OBJ_SECT)
1124*cdf0e10cSrcweir 		eNewKindA = SDRCIRC_SECT;
1125*cdf0e10cSrcweir 	else if(meCircleKind == OBJ_CARC)
1126*cdf0e10cSrcweir 		eNewKindA = SDRCIRC_ARC;
1127*cdf0e10cSrcweir 	else if(meCircleKind == OBJ_CCUT)
1128*cdf0e10cSrcweir 		eNewKindA = SDRCIRC_CUT;
1129*cdf0e10cSrcweir 
1130*cdf0e10cSrcweir 	SdrCircKind eOldKindA = ((SdrCircKindItem&)rSet.Get(SDRATTR_CIRCKIND)).GetValue();
1131*cdf0e10cSrcweir 	sal_Int32 nOldStartWink = ((SdrCircStartAngleItem&)rSet.Get(SDRATTR_CIRCSTARTANGLE)).GetValue();
1132*cdf0e10cSrcweir 	sal_Int32 nOldEndWink = ((SdrCircEndAngleItem&)rSet.Get(SDRATTR_CIRCENDANGLE)).GetValue();
1133*cdf0e10cSrcweir 
1134*cdf0e10cSrcweir 	if(eNewKindA != eOldKindA || nStartWink != nOldStartWink || nEndWink != nOldEndWink)
1135*cdf0e10cSrcweir 	{
1136*cdf0e10cSrcweir 		// #81921# since SetItem() implicitly calls ImpSetAttrToCircInfo()
1137*cdf0e10cSrcweir 		// setting the item directly is necessary here.
1138*cdf0e10cSrcweir 		if(eNewKindA != eOldKindA)
1139*cdf0e10cSrcweir 		{
1140*cdf0e10cSrcweir 			GetProperties().SetObjectItemDirect(SdrCircKindItem(eNewKindA));
1141*cdf0e10cSrcweir 		}
1142*cdf0e10cSrcweir 
1143*cdf0e10cSrcweir 		if(nStartWink != nOldStartWink)
1144*cdf0e10cSrcweir 		{
1145*cdf0e10cSrcweir 			GetProperties().SetObjectItemDirect(SdrCircStartAngleItem(nStartWink));
1146*cdf0e10cSrcweir 		}
1147*cdf0e10cSrcweir 
1148*cdf0e10cSrcweir 		if(nEndWink != nOldEndWink)
1149*cdf0e10cSrcweir 		{
1150*cdf0e10cSrcweir 			GetProperties().SetObjectItemDirect(SdrCircEndAngleItem(nEndWink));
1151*cdf0e10cSrcweir 		}
1152*cdf0e10cSrcweir 
1153*cdf0e10cSrcweir 		SetXPolyDirty();
1154*cdf0e10cSrcweir 		ImpSetAttrToCircInfo();
1155*cdf0e10cSrcweir 	}
1156*cdf0e10cSrcweir }
1157*cdf0e10cSrcweir 
1158*cdf0e10cSrcweir SdrObject* SdrCircObj::DoConvertToPolyObj(sal_Bool bBezier) const
1159*cdf0e10cSrcweir {
1160*cdf0e10cSrcweir 	const sal_Bool bFill(OBJ_CARC == meCircleKind ? sal_False : sal_True);
1161*cdf0e10cSrcweir 	const basegfx::B2DPolygon aCircPolygon(ImpCalcXPolyCirc(meCircleKind, aRect, nStartWink, nEndWink));
1162*cdf0e10cSrcweir 	SdrObject* pRet = ImpConvertMakeObj(basegfx::B2DPolyPolygon(aCircPolygon), bFill, bBezier);
1163*cdf0e10cSrcweir 	pRet = ImpConvertAddText(pRet, bBezier);
1164*cdf0e10cSrcweir 
1165*cdf0e10cSrcweir 	return pRet;
1166*cdf0e10cSrcweir }
1167*cdf0e10cSrcweir 
1168*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1169*cdf0e10cSrcweir // eof
1170