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