1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svx.hxx" 30 31 #include <svx/svdorect.hxx> 32 #include <math.h> 33 #include <stdlib.h> 34 #include <svx/xpool.hxx> 35 #include <svx/xpoly.hxx> 36 #include <svx/svdattr.hxx> 37 #include <svx/svdpool.hxx> 38 #include <svx/svdtrans.hxx> 39 #include <svx/svdetc.hxx> 40 #include <svx/svddrag.hxx> 41 #include <svx/svdmodel.hxx> 42 #include <svx/svdpage.hxx> 43 #include <svx/svdocapt.hxx> // fuer Import von SdrFileVersion 2 44 #include <svx/svdpagv.hxx> // fuer 45 #include <svx/svdview.hxx> // das 46 #include <svx/svdundo.hxx> // Macro-Beispiel 47 #include <svx/svdopath.hxx> 48 #include "svx/svdglob.hxx" // Stringcache 49 #include "svx/svdstr.hrc" // Objektname 50 #include <svx/xflclit.hxx> 51 #include <svx/xlnclit.hxx> 52 #include <svx/xlnwtit.hxx> 53 #include "svdoimp.hxx" 54 #include <svx/sdr/properties/rectangleproperties.hxx> 55 #include <svx/sdr/contact/viewcontactofsdrrectobj.hxx> 56 #include <basegfx/polygon/b2dpolygon.hxx> 57 #include <basegfx/polygon/b2dpolygontools.hxx> 58 59 ////////////////////////////////////////////////////////////////////////////// 60 // BaseProperties section 61 62 sdr::properties::BaseProperties* SdrRectObj::CreateObjectSpecificProperties() 63 { 64 return new sdr::properties::RectangleProperties(*this); 65 } 66 67 ////////////////////////////////////////////////////////////////////////////// 68 // DrawContact section 69 70 sdr::contact::ViewContact* SdrRectObj::CreateObjectSpecificViewContact() 71 { 72 return new sdr::contact::ViewContactOfSdrRectObj(*this); 73 } 74 75 ////////////////////////////////////////////////////////////////////////////// 76 77 TYPEINIT1(SdrRectObj,SdrTextObj); 78 79 SdrRectObj::SdrRectObj() 80 : mpXPoly(0L) 81 { 82 bClosedObj=sal_True; 83 } 84 85 SdrRectObj::SdrRectObj(const Rectangle& rRect) 86 : SdrTextObj(rRect), 87 mpXPoly(NULL) 88 { 89 bClosedObj=sal_True; 90 } 91 92 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind) 93 : SdrTextObj(eNewTextKind), 94 mpXPoly(NULL) 95 { 96 DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT || 97 eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT, 98 "SdrRectObj::SdrRectObj(SdrObjKind) ist nur fuer Textrahmen gedacht"); 99 bClosedObj=sal_True; 100 } 101 102 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind, const Rectangle& rRect) 103 : SdrTextObj(eNewTextKind,rRect), 104 mpXPoly(NULL) 105 { 106 DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT || 107 eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT, 108 "SdrRectObj::SdrRectObj(SdrObjKind,...) ist nur fuer Textrahmen gedacht"); 109 bClosedObj=sal_True; 110 } 111 112 SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect, SvStream& rInput, const String& rBaseURL, sal_uInt16 eFormat) 113 : SdrTextObj(eNewTextKind,rNewRect,rInput,rBaseURL,eFormat), 114 mpXPoly(NULL) 115 { 116 DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT || 117 eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT, 118 "SdrRectObj::SdrRectObj(SdrObjKind,...) ist nur fuer Textrahmen gedacht"); 119 bClosedObj=sal_True; 120 } 121 122 SdrRectObj::~SdrRectObj() 123 { 124 if(mpXPoly) 125 { 126 delete mpXPoly; 127 } 128 } 129 130 void SdrRectObj::SetXPolyDirty() 131 { 132 if(mpXPoly) 133 { 134 delete mpXPoly; 135 mpXPoly = 0L; 136 } 137 } 138 139 FASTBOOL SdrRectObj::PaintNeedsXPoly(long nEckRad) const 140 { 141 FASTBOOL bNeed=aGeo.nDrehWink!=0 || aGeo.nShearWink!=0 || nEckRad!=0; 142 return bNeed; 143 } 144 145 XPolygon SdrRectObj::ImpCalcXPoly(const Rectangle& rRect1, long nRad1) const 146 { 147 XPolygon aXPoly(rRect1,nRad1,nRad1); 148 const sal_uInt16 nPointAnz(aXPoly.GetPointCount()); 149 XPolygon aNeuPoly(nPointAnz+1); 150 sal_uInt16 nShift=nPointAnz-2; 151 if (nRad1!=0) nShift=nPointAnz-5; 152 sal_uInt16 j=nShift; 153 for (sal_uInt16 i=1; i<nPointAnz; i++) { 154 aNeuPoly[i]=aXPoly[j]; 155 aNeuPoly.SetFlags(i,aXPoly.GetFlags(j)); 156 j++; 157 if (j>=nPointAnz) j=1; 158 } 159 aNeuPoly[0]=rRect1.BottomCenter(); 160 aNeuPoly[nPointAnz]=aNeuPoly[0]; 161 aXPoly=aNeuPoly; 162 163 // Die Winkelangaben beziehen sich immer auf die linke obere Ecke von !aRect! 164 if (aGeo.nShearWink!=0) ShearXPoly(aXPoly,aRect.TopLeft(),aGeo.nTan); 165 if (aGeo.nDrehWink!=0) RotateXPoly(aXPoly,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); 166 return aXPoly; 167 } 168 169 void SdrRectObj::RecalcXPoly() 170 { 171 mpXPoly = new XPolygon(ImpCalcXPoly(aRect,GetEckenradius())); 172 } 173 174 const XPolygon& SdrRectObj::GetXPoly() const 175 { 176 if(!mpXPoly) 177 { 178 ((SdrRectObj*)this)->RecalcXPoly(); 179 } 180 181 return *mpXPoly; 182 } 183 184 void SdrRectObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const 185 { 186 FASTBOOL bNoTextFrame=!IsTextFrame(); 187 rInfo.bResizeFreeAllowed=bNoTextFrame || aGeo.nDrehWink%9000==0; 188 rInfo.bResizePropAllowed=sal_True; 189 rInfo.bRotateFreeAllowed=sal_True; 190 rInfo.bRotate90Allowed =sal_True; 191 rInfo.bMirrorFreeAllowed=bNoTextFrame; 192 rInfo.bMirror45Allowed =bNoTextFrame; 193 rInfo.bMirror90Allowed =bNoTextFrame; 194 195 // allow transparence 196 rInfo.bTransparenceAllowed = sal_True; 197 198 // gradient depends on fillstyle 199 XFillStyle eFillStyle = ((XFillStyleItem&)(GetObjectItem(XATTR_FILLSTYLE))).GetValue(); 200 rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT); 201 202 rInfo.bShearAllowed =bNoTextFrame; 203 rInfo.bEdgeRadiusAllowed=sal_True; 204 205 FASTBOOL bCanConv=!HasText() || ImpCanConvTextToCurve(); 206 if (bCanConv && !bNoTextFrame && !HasText()) { 207 bCanConv=HasFill() || HasLine(); 208 } 209 rInfo.bCanConvToPath =bCanConv; 210 rInfo.bCanConvToPoly =bCanConv; 211 rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); 212 } 213 214 sal_uInt16 SdrRectObj::GetObjIdentifier() const 215 { 216 if (IsTextFrame()) return sal_uInt16(eTextKind); 217 else return sal_uInt16(OBJ_RECT); 218 } 219 220 void SdrRectObj::TakeUnrotatedSnapRect(Rectangle& rRect) const 221 { 222 rRect=aRect; 223 if (aGeo.nShearWink!=0) { 224 long nDst=Round((aRect.Bottom()-aRect.Top())*aGeo.nTan); 225 if (aGeo.nShearWink>0) { 226 Point aRef(rRect.TopLeft()); 227 rRect.Left()-=nDst; 228 Point aTmpPt(rRect.TopLeft()); 229 RotatePoint(aTmpPt,aRef,aGeo.nSin,aGeo.nCos); 230 aTmpPt-=rRect.TopLeft(); 231 rRect.Move(aTmpPt.X(),aTmpPt.Y()); 232 } else { 233 rRect.Right()-=nDst; 234 } 235 } 236 } 237 238 void SdrRectObj::TakeObjNameSingul(XubString& rName) const 239 { 240 if (IsTextFrame()) 241 { 242 SdrTextObj::TakeObjNameSingul(rName); 243 } 244 else 245 { 246 sal_uInt16 nResId=STR_ObjNameSingulRECT; 247 if (aGeo.nShearWink!=0) { 248 nResId+=4; // Parallelogramm oder Raute 249 // Raute ist nicht, weil Shear die vertikalen Kanten verlaengert! 250 // Wenn Zeit ist, werde ich das mal berechnen. 251 } else { 252 if (aRect.GetWidth()==aRect.GetHeight()) nResId+=2; // Quadrat 253 } 254 if (GetEckenradius()!=0) nResId+=8; // abgerundet 255 rName=ImpGetResStr(nResId); 256 257 String aName( GetName() ); 258 if(aName.Len()) 259 { 260 rName += sal_Unicode(' '); 261 rName += sal_Unicode('\''); 262 rName += aName; 263 rName += sal_Unicode('\''); 264 } 265 } 266 } 267 268 void SdrRectObj::TakeObjNamePlural(XubString& rName) const 269 { 270 if (IsTextFrame()) SdrTextObj::TakeObjNamePlural(rName); 271 else { 272 sal_uInt16 nResId=STR_ObjNamePluralRECT; 273 if (aGeo.nShearWink!=0) { 274 nResId+=4; // Parallelogramm oder Raute 275 } else { 276 if (aRect.GetWidth()==aRect.GetHeight()) nResId+=2; // Quadrat 277 } 278 if (GetEckenradius()!=0) nResId+=8; // abgerundet 279 rName=ImpGetResStr(nResId); 280 } 281 } 282 283 void SdrRectObj::operator=(const SdrObject& rObj) 284 { 285 SdrTextObj::operator=(rObj); 286 } 287 288 basegfx::B2DPolyPolygon SdrRectObj::TakeXorPoly() const 289 { 290 XPolyPolygon aXPP; 291 aXPP.Insert(ImpCalcXPoly(aRect,GetEckenradius())); 292 return aXPP.getB2DPolyPolygon(); 293 } 294 295 void SdrRectObj::RecalcSnapRect() 296 { 297 long nEckRad=GetEckenradius(); 298 if ((aGeo.nDrehWink!=0 || aGeo.nShearWink!=0) && nEckRad!=0) { 299 maSnapRect=GetXPoly().GetBoundRect(); 300 } else { 301 SdrTextObj::RecalcSnapRect(); 302 } 303 } 304 305 void SdrRectObj::NbcSetSnapRect(const Rectangle& rRect) 306 { 307 SdrTextObj::NbcSetSnapRect(rRect); 308 SetXPolyDirty(); 309 } 310 311 void SdrRectObj::NbcSetLogicRect(const Rectangle& rRect) 312 { 313 SdrTextObj::NbcSetLogicRect(rRect); 314 SetXPolyDirty(); 315 } 316 317 sal_uInt32 SdrRectObj::GetHdlCount() const 318 { 319 return IsTextFrame() ? 10 : 9; 320 } 321 322 SdrHdl* SdrRectObj::GetHdl(sal_uInt32 nHdlNum) const 323 { 324 SdrHdl* pH = NULL; 325 Point aPnt; 326 SdrHdlKind eKind = HDL_MOVE; 327 328 if(!IsTextFrame()) 329 { 330 nHdlNum++; 331 } 332 333 switch(nHdlNum) 334 { 335 case 0: 336 { 337 pH = new ImpTextframeHdl(aRect); 338 pH->SetObj((SdrObject*)this); 339 pH->SetDrehWink(aGeo.nDrehWink); 340 break; 341 } 342 case 1: 343 { 344 long a = GetEckenradius(); 345 long b = Max(aRect.GetWidth(),aRect.GetHeight())/2; // Wird aufgerundet, da GetWidth() eins draufaddiert 346 if (a>b) a=b; 347 if (a<0) a=0; 348 aPnt=aRect.TopLeft(); 349 aPnt.X()+=a; 350 eKind = HDL_CIRC; 351 break; 352 } 353 case 2: aPnt=aRect.TopLeft(); eKind = HDL_UPLFT; break; // Oben links 354 case 3: aPnt=aRect.TopCenter(); eKind = HDL_UPPER; break; // Oben 355 case 4: aPnt=aRect.TopRight(); eKind = HDL_UPRGT; break; // Oben rechts 356 case 5: aPnt=aRect.LeftCenter(); eKind = HDL_LEFT ; break; // Links 357 case 6: aPnt=aRect.RightCenter(); eKind = HDL_RIGHT; break; // Rechts 358 case 7: aPnt=aRect.BottomLeft(); eKind = HDL_LWLFT; break; // Unten links 359 case 8: aPnt=aRect.BottomCenter(); eKind = HDL_LOWER; break; // Unten 360 case 9: aPnt=aRect.BottomRight(); eKind = HDL_LWRGT; break; // Unten rechts 361 } 362 363 if(!pH) 364 { 365 if(aGeo.nShearWink) 366 { 367 ShearPoint(aPnt,aRect.TopLeft(),aGeo.nTan); 368 } 369 370 if(aGeo.nDrehWink) 371 { 372 RotatePoint(aPnt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); 373 } 374 375 pH = new SdrHdl(aPnt,eKind); 376 pH->SetObj((SdrObject*)this); 377 pH->SetDrehWink(aGeo.nDrehWink); 378 } 379 380 return pH; 381 } 382 383 //////////////////////////////////////////////////////////////////////////////////////////////////// 384 385 bool SdrRectObj::hasSpecialDrag() const 386 { 387 return true; 388 } 389 390 bool SdrRectObj::beginSpecialDrag(SdrDragStat& rDrag) const 391 { 392 const bool bRad(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind()); 393 394 if(bRad) 395 { 396 rDrag.SetEndDragChangesAttributes(true); 397 398 return true; 399 } 400 401 return SdrTextObj::beginSpecialDrag(rDrag); 402 } 403 404 bool SdrRectObj::applySpecialDrag(SdrDragStat& rDrag) 405 { 406 const bool bRad(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind()); 407 408 if (bRad) 409 { 410 Rectangle aBoundRect0; 411 Point aPt(rDrag.GetNow()); 412 413 if(aGeo.nDrehWink) 414 RotatePoint(aPt,aRect.TopLeft(),-aGeo.nSin,aGeo.nCos); 415 416 sal_Int32 nRad(aPt.X() - aRect.Left()); 417 418 if (nRad < 0) 419 nRad = 0; 420 421 if(nRad != GetEckenradius()) 422 { 423 NbcSetEckenradius(nRad); 424 } 425 426 return true; 427 } 428 else 429 { 430 return SdrTextObj::applySpecialDrag(rDrag); 431 } 432 } 433 434 String SdrRectObj::getSpecialDragComment(const SdrDragStat& rDrag) const 435 { 436 const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj()); 437 438 if(bCreateComment) 439 { 440 return String(); 441 } 442 else 443 { 444 const bool bRad(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind()); 445 446 if(bRad) 447 { 448 Point aPt(rDrag.GetNow()); 449 450 // -sin fuer Umkehrung 451 if(aGeo.nDrehWink) 452 RotatePoint(aPt, aRect.TopLeft(), -aGeo.nSin, aGeo.nCos); 453 454 sal_Int32 nRad(aPt.X() - aRect.Left()); 455 456 if(nRad < 0) 457 nRad = 0; 458 459 XubString aStr; 460 461 ImpTakeDescriptionStr(STR_DragRectEckRad, aStr); 462 aStr.AppendAscii(" ("); 463 aStr += GetMetrStr(nRad); 464 aStr += sal_Unicode(')'); 465 466 return aStr; 467 } 468 else 469 { 470 return SdrTextObj::getSpecialDragComment(rDrag); 471 } 472 } 473 } 474 475 //////////////////////////////////////////////////////////////////////////////////////////////////// 476 477 basegfx::B2DPolyPolygon SdrRectObj::TakeCreatePoly(const SdrDragStat& rDrag) const 478 { 479 Rectangle aRect1; 480 rDrag.TakeCreateRect(aRect1); 481 aRect1.Justify(); 482 483 basegfx::B2DPolyPolygon aRetval; 484 aRetval.append(ImpCalcXPoly(aRect1,GetEckenradius()).getB2DPolygon()); 485 return aRetval; 486 } 487 488 Pointer SdrRectObj::GetCreatePointer() const 489 { 490 if (IsTextFrame()) return Pointer(POINTER_DRAW_TEXT); 491 return Pointer(POINTER_DRAW_RECT); 492 } 493 494 void SdrRectObj::NbcMove(const Size& rSiz) 495 { 496 SdrTextObj::NbcMove(rSiz); 497 SetXPolyDirty(); 498 } 499 500 void SdrRectObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) 501 { 502 SdrTextObj::NbcResize(rRef,xFact,yFact); 503 SetXPolyDirty(); 504 } 505 506 void SdrRectObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs) 507 { 508 SdrTextObj::NbcRotate(rRef,nWink,sn,cs); 509 SetXPolyDirty(); 510 } 511 512 void SdrRectObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear) 513 { 514 SdrTextObj::NbcShear(rRef,nWink,tn,bVShear); 515 SetXPolyDirty(); 516 } 517 518 void SdrRectObj::NbcMirror(const Point& rRef1, const Point& rRef2) 519 { 520 SdrTextObj::NbcMirror(rRef1,rRef2); 521 SetXPolyDirty(); 522 } 523 524 FASTBOOL SdrRectObj::DoMacro(const SdrObjMacroHitRec& rRec) 525 { 526 return SdrTextObj::DoMacro(rRec); 527 } 528 529 XubString SdrRectObj::GetMacroPopupComment(const SdrObjMacroHitRec& rRec) const 530 { 531 return SdrTextObj::GetMacroPopupComment(rRec); 532 } 533 534 SdrGluePoint SdrRectObj::GetVertexGluePoint(sal_uInt16 nPosNum) const 535 { 536 sal_Int32 nWdt = ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue(); 537 538 // #i25616# 539 if(!LineIsOutsideGeometry()) 540 { 541 nWdt++; 542 nWdt /= 2; 543 } 544 545 Point aPt; 546 switch (nPosNum) { 547 case 0: aPt=aRect.TopCenter(); aPt.Y()-=nWdt; break; 548 case 1: aPt=aRect.RightCenter(); aPt.X()+=nWdt; break; 549 case 2: aPt=aRect.BottomCenter(); aPt.Y()+=nWdt; break; 550 case 3: aPt=aRect.LeftCenter(); aPt.X()-=nWdt; break; 551 } 552 if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan); 553 if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); 554 aPt-=GetSnapRect().Center(); 555 SdrGluePoint aGP(aPt); 556 aGP.SetPercent(sal_False); 557 return aGP; 558 } 559 560 SdrGluePoint SdrRectObj::GetCornerGluePoint(sal_uInt16 nPosNum) const 561 { 562 sal_Int32 nWdt = ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue(); 563 564 // #i25616# 565 if(!LineIsOutsideGeometry()) 566 { 567 nWdt++; 568 nWdt /= 2; 569 } 570 571 Point aPt; 572 switch (nPosNum) { 573 case 0: aPt=aRect.TopLeft(); aPt.X()-=nWdt; aPt.Y()-=nWdt; break; 574 case 1: aPt=aRect.TopRight(); aPt.X()+=nWdt; aPt.Y()-=nWdt; break; 575 case 2: aPt=aRect.BottomRight(); aPt.X()+=nWdt; aPt.Y()+=nWdt; break; 576 case 3: aPt=aRect.BottomLeft(); aPt.X()-=nWdt; aPt.Y()+=nWdt; break; 577 } 578 if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan); 579 if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); 580 aPt-=GetSnapRect().Center(); 581 SdrGluePoint aGP(aPt); 582 aGP.SetPercent(sal_False); 583 return aGP; 584 } 585 586 SdrObject* SdrRectObj::DoConvertToPolyObj(sal_Bool bBezier) const 587 { 588 XPolygon aXP(ImpCalcXPoly(aRect,GetEckenradius())); 589 { // #40608# Nur Uebergangsweise bis zum neuen TakeContour() 590 aXP.Remove(0,1); 591 aXP[aXP.GetPointCount()-1]=aXP[0]; 592 } 593 594 basegfx::B2DPolyPolygon aPolyPolygon(aXP.getB2DPolygon()); 595 aPolyPolygon.removeDoublePoints(); 596 SdrObject* pRet = 0L; 597 598 if(!IsTextFrame() || HasFill() || HasLine()) 599 { 600 pRet = ImpConvertMakeObj(aPolyPolygon, sal_True, bBezier); 601 } 602 603 pRet = ImpConvertAddText(pRet, bBezier); 604 605 return pRet; 606 } 607 608 void SdrRectObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) 609 { 610 SdrTextObj::Notify(rBC,rHint); 611 SetXPolyDirty(); // wg. Eckenradius 612 } 613 614 void SdrRectObj::RestGeoData(const SdrObjGeoData& rGeo) 615 { 616 SdrTextObj::RestGeoData(rGeo); 617 SetXPolyDirty(); 618 } 619 620 // eof 621