update credits
[LibreOffice.git] / svx / source / svdraw / svdoashp.cxx
blobbabab98398e083bbeaa9a1ee8deea03f7042453d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/svdoashp.hxx>
21 #include "svx/unoapi.hxx"
22 #include <svx/unoshape.hxx>
23 #include <ucbhelper/content.hxx>
24 #include <unotools/datetime.hxx>
25 #include <sfx2/lnkbase.hxx>
26 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
27 #include <com/sun/star/drawing/XShape.hpp>
28 #include <com/sun/star/drawing/XCustomShapeEngine.hpp>
29 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/awt/Rectangle.hpp>
32 #include <comphelper/processfactory.hxx>
33 #include <svl/urihelper.hxx>
34 #include <com/sun/star/uno/Sequence.h>
35 #include <svx/svdogrp.hxx>
36 #include <tools/helpers.hxx>
37 #include <svx/svddrag.hxx>
38 #include <svx/xpool.hxx>
39 #include <svx/xpoly.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <svx/svdpage.hxx>
42 #include "svx/svditer.hxx"
43 #include <svx/svdobj.hxx>
44 #include <svx/svdtrans.hxx>
45 #include <svx/svdetc.hxx>
46 #include <svx/svdattrx.hxx> // NotPersistItems
47 #include <svx/svdoedge.hxx> // for broadcasting connectors to Move
48 #include "svx/svdglob.hxx" // StringCache
49 #include "svx/svdstr.hrc" // the object's name
50 #include <editeng/eeitem.hxx>
51 #include "editeng/editstat.hxx"
52 #include <svx/svdoutl.hxx>
53 #include <editeng/outlobj.hxx>
54 #include <svx/sdtfchim.hxx>
55 #include "svx/EnhancedCustomShapeGeometry.hxx"
56 #include "svx/EnhancedCustomShapeTypeNames.hxx"
57 #include "svx/EnhancedCustomShape2d.hxx"
58 #include <com/sun/star/beans/PropertyValues.hpp>
59 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
60 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
61 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
62 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
63 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
64 #include <editeng/writingmodeitem.hxx>
65 #include <svx/xlnclit.hxx>
66 #include <svx/svxids.hrc>
67 #include <svl/whiter.hxx>
68 #include <svx/sdr/properties/customshapeproperties.hxx>
69 #include <svx/sdr/contact/viewcontactofsdrobjcustomshape.hxx>
70 #include <svx/xlntrit.hxx>
71 #include <svx/xfltrit.hxx>
72 #include <svx/xflclit.hxx>
73 #include <svx/xflgrit.hxx>
74 #include <svx/xflhtit.hxx>
75 #include <svx/xbtmpit.hxx>
76 #include <vcl/bmpacc.hxx>
77 #include <svx/svdview.hxx>
78 #include <basegfx/polygon/b2dpolypolygontools.hxx>
79 #include <basegfx/matrix/b2dhommatrix.hxx>
80 #include <basegfx/matrix/b2dhommatrixtools.hxx>
81 #include <basegfx/tools/unotools.hxx>
82 #include "svdconv.hxx"
84 using namespace ::com::sun::star;
85 using namespace ::com::sun::star::uno;
86 using namespace ::com::sun::star::lang;
87 using namespace ::com::sun::star::beans;
88 using namespace ::com::sun::star::drawing;
90 static void lcl_ShapeSegmentFromBinary( EnhancedCustomShapeSegment& rSegInfo, sal_uInt16 nSDat )
92 switch( nSDat >> 8 )
94 case 0x00 :
95 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::LINETO;
96 rSegInfo.Count = nSDat & 0xff;
97 if ( !rSegInfo.Count )
98 rSegInfo.Count = 1;
99 break;
100 case 0x20 :
101 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CURVETO;
102 rSegInfo.Count = nSDat & 0xff;
103 if ( !rSegInfo.Count )
104 rSegInfo.Count = 1;
105 break;
106 case 0x40 :
107 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::MOVETO;
108 rSegInfo.Count = nSDat & 0xff;
109 if ( !rSegInfo.Count )
110 rSegInfo.Count = 1;
111 break;
112 case 0x60 :
113 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
114 rSegInfo.Count = 0;
115 break;
116 case 0x80 :
117 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
118 rSegInfo.Count = 0;
119 break;
120 case 0xa1 :
121 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO;
122 rSegInfo.Count = ( nSDat & 0xff ) / 3;
123 break;
124 case 0xa2 :
125 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE;
126 rSegInfo.Count = ( nSDat & 0xff ) / 3;
127 break;
128 case 0xa3 :
129 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARCTO;
130 rSegInfo.Count = ( nSDat & 0xff ) >> 2;
131 break;
132 case 0xa4 :
133 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARC;
134 rSegInfo.Count = ( nSDat & 0xff ) >> 2;
135 break;
136 case 0xa5 :
137 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO;
138 rSegInfo.Count = ( nSDat & 0xff ) >> 2;
139 break;
140 case 0xa6 :
141 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC;
142 rSegInfo.Count = ( nSDat & 0xff ) >> 2;
143 break;
144 case 0xa7 :
145 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX;
146 rSegInfo.Count = nSDat & 0xff;
147 break;
148 case 0xa8 :
149 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY;
150 rSegInfo.Count = nSDat & 0xff;
151 break;
152 case 0xaa :
153 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOFILL;
154 rSegInfo.Count = 0;
155 break;
156 case 0xab :
157 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOSTROKE;
158 rSegInfo.Count = 0;
159 break;
160 default:
161 case 0xf8 :
162 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::UNKNOWN;
163 rSegInfo.Count = nSDat;
164 break;
166 return;
169 static MSO_SPT ImpGetCustomShapeType( const SdrObjCustomShape& rCustoShape )
171 MSO_SPT eRetValue = mso_sptNil;
173 OUString aEngine( ( (SdrCustomShapeEngineItem&)rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ) ).GetValue() );
174 if ( aEngine.isEmpty() || aEngine == "com.sun.star.drawing.EnhancedCustomShapeEngine" )
176 OUString sShapeType;
177 const OUString sType( "Type" );
178 SdrCustomShapeGeometryItem& rGeometryItem( (SdrCustomShapeGeometryItem&)rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
179 Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
180 if ( pAny && ( *pAny >>= sShapeType ) )
181 eRetValue = EnhancedCustomShapeTypeNames::Get( sShapeType );
183 return eRetValue;
186 static bool ImpVerticalSwitch( const SdrObjCustomShape& rCustoShape )
188 bool bRet = false;
189 MSO_SPT eShapeType( ImpGetCustomShapeType( rCustoShape ) );
190 switch( eShapeType )
192 case mso_sptAccentBorderCallout90 : // 2 ortho
193 case mso_sptBorderCallout1 : // 2 diag
194 case mso_sptBorderCallout2 : // 3
196 bRet = true;
198 break;
199 default: break;
201 return bRet;
204 // #i37011# create a clone with all attributes changed to shadow attributes
205 // and translation executed, too.
206 SdrObject* ImpCreateShadowObjectClone(const SdrObject& rOriginal, const SfxItemSet& rOriginalSet)
208 SdrObject* pRetval = 0L;
209 const sal_Bool bShadow(((SdrShadowItem&)rOriginalSet.Get(SDRATTR_SHADOW)).GetValue());
211 if(bShadow)
213 // create a shadow representing object
214 const sal_Int32 nXDist(((SdrShadowXDistItem&)(rOriginalSet.Get(SDRATTR_SHADOWXDIST))).GetValue());
215 const sal_Int32 nYDist(((SdrShadowYDistItem&)(rOriginalSet.Get(SDRATTR_SHADOWYDIST))).GetValue());
216 const ::Color aShadowColor(((SdrShadowColorItem&)(rOriginalSet.Get(SDRATTR_SHADOWCOLOR))).GetColorValue());
217 const sal_uInt16 nShadowTransparence(((SdrShadowTransparenceItem&)(rOriginalSet.Get(SDRATTR_SHADOWTRANSPARENCE))).GetValue());
218 pRetval = rOriginal.Clone();
219 DBG_ASSERT(pRetval, "ImpCreateShadowObjectClone: Could not clone object (!)");
221 // look for used stuff
222 SdrObjListIter aIterator(rOriginal);
223 bool bLineUsed(false);
224 bool bAllFillUsed(false);
225 bool bSolidFillUsed(false);
226 bool bGradientFillUsed(false);
227 bool bHatchFillUsed(false);
228 bool bBitmapFillUsed(false);
230 while(aIterator.IsMore())
232 SdrObject* pObj = aIterator.Next();
233 XFillStyle eFillStyle = ((XFillStyleItem&)(pObj->GetMergedItem(XATTR_FILLSTYLE))).GetValue();
235 if(!bLineUsed)
237 XLineStyle eLineStyle = ((XLineStyleItem&)(pObj->GetMergedItem(XATTR_LINESTYLE))).GetValue();
239 if(XLINE_NONE != eLineStyle)
241 bLineUsed = true;
245 if(!bAllFillUsed)
247 if(!bSolidFillUsed && XFILL_SOLID == eFillStyle)
249 bSolidFillUsed = true;
250 bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
252 if(!bGradientFillUsed && XFILL_GRADIENT == eFillStyle)
254 bGradientFillUsed = true;
255 bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
257 if(!bHatchFillUsed && XFILL_HATCH == eFillStyle)
259 bHatchFillUsed = true;
260 bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
262 if(!bBitmapFillUsed && XFILL_BITMAP == eFillStyle)
264 bBitmapFillUsed = true;
265 bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
270 // translate to shadow coordinates
271 pRetval->NbcMove(Size(nXDist, nYDist));
273 // set items as needed
274 SfxItemSet aTempSet(rOriginalSet);
276 // if a SvxWritingModeItem (Top->Bottom) is set the text object
277 // is creating a paraobject, but paraobjects can not be created without model. So
278 // we are preventing the crash by setting the writing mode always left to right,
279 // this is not bad since our shadow geometry does not contain text.
280 aTempSet.Put( SvxWritingModeItem( com::sun::star::text::WritingMode_LR_TB, SDRATTR_TEXTDIRECTION ) );
282 // no shadow
283 aTempSet.Put(SdrShadowItem(sal_False));
284 aTempSet.Put(SdrShadowXDistItem(0L));
285 aTempSet.Put(SdrShadowYDistItem(0L));
287 // line color and transparency like shadow
288 if(bLineUsed)
290 aTempSet.Put(XLineColorItem(String(), aShadowColor));
291 aTempSet.Put(XLineTransparenceItem(nShadowTransparence));
294 // fill color and transparency like shadow
295 if(bSolidFillUsed)
297 aTempSet.Put(XFillColorItem(String(), aShadowColor));
298 aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
301 // gradient and transparency like shadow
302 if(bGradientFillUsed)
304 XGradient aGradient(((XFillGradientItem&)(rOriginalSet.Get(XATTR_FILLGRADIENT))).GetGradientValue());
305 sal_uInt8 nStartLuminance(aGradient.GetStartColor().GetLuminance());
306 sal_uInt8 nEndLuminance(aGradient.GetEndColor().GetLuminance());
308 if(aGradient.GetStartIntens() != 100)
310 nStartLuminance = (sal_uInt8)(nStartLuminance * ((double)aGradient.GetStartIntens() / 100.0));
313 if(aGradient.GetEndIntens() != 100)
315 nEndLuminance = (sal_uInt8)(nEndLuminance * ((double)aGradient.GetEndIntens() / 100.0));
318 ::Color aStartColor(
319 (sal_uInt8)((nStartLuminance * aShadowColor.GetRed()) / 256),
320 (sal_uInt8)((nStartLuminance * aShadowColor.GetGreen()) / 256),
321 (sal_uInt8)((nStartLuminance * aShadowColor.GetBlue()) / 256));
323 ::Color aEndColor(
324 (sal_uInt8)((nEndLuminance * aShadowColor.GetRed()) / 256),
325 (sal_uInt8)((nEndLuminance * aShadowColor.GetGreen()) / 256),
326 (sal_uInt8)((nEndLuminance * aShadowColor.GetBlue()) / 256));
328 aGradient.SetStartColor(aStartColor);
329 aGradient.SetEndColor(aEndColor);
330 aTempSet.Put(XFillGradientItem(aGradient));
331 aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
334 // hatch and transparency like shadow
335 if(bHatchFillUsed)
337 XHatch aHatch(((XFillHatchItem&)(rOriginalSet.Get(XATTR_FILLHATCH))).GetHatchValue());
338 aHatch.SetColor(aShadowColor);
339 aTempSet.Put(XFillHatchItem(aTempSet.GetPool(), aHatch));
340 aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
343 // bitmap and transparency like shadow
344 if(bBitmapFillUsed)
346 GraphicObject aGraphicObject(((XFillBitmapItem&)(rOriginalSet.Get(XATTR_FILLBITMAP))).GetGraphicObject());
347 const BitmapEx aBitmapEx(aGraphicObject.GetGraphic().GetBitmapEx());
348 Bitmap aBitmap(aBitmapEx.GetBitmap());
350 if(!aBitmap.IsEmpty())
352 BitmapReadAccess* pReadAccess = aBitmap.AcquireReadAccess();
354 if(pReadAccess)
356 Bitmap aDestBitmap(aBitmap.GetSizePixel(), 24L);
357 BitmapWriteAccess* pWriteAccess = aDestBitmap.AcquireWriteAccess();
359 if(pWriteAccess)
361 for(sal_Int32 y(0L); y < pReadAccess->Height(); y++)
363 for(sal_Int32 x(0L); x < pReadAccess->Width(); x++)
365 sal_uInt16 nLuminance((sal_uInt16)pReadAccess->GetLuminance(y, x) + 1);
366 const BitmapColor aDestColor(
367 (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetRed()) >> 8L),
368 (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetGreen()) >> 8L),
369 (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetBlue()) >> 8L));
370 pWriteAccess->SetPixel(y, x, aDestColor);
374 aDestBitmap.ReleaseAccess(pWriteAccess);
377 aBitmap.ReleaseAccess(pReadAccess);
379 if(aBitmapEx.IsTransparent())
381 if(aBitmapEx.IsAlpha())
383 aGraphicObject.SetGraphic(Graphic(BitmapEx(aDestBitmap, aBitmapEx.GetAlpha())));
385 else
387 aGraphicObject.SetGraphic(Graphic(BitmapEx(aDestBitmap, aBitmapEx.GetMask())));
390 else
392 aGraphicObject.SetGraphic(Graphic(aDestBitmap));
397 aTempSet.Put(XFillBitmapItem(aTempSet.GetPool(), aGraphicObject));
398 aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
401 // set attributes and paint shadow object
402 pRetval->SetMergedItemSet( aTempSet );
404 return pRetval;
407 ////////////////////////////////////////////////////////////////////////////////////////////////////
409 Reference< XCustomShapeEngine > SdrObjCustomShape::GetCustomShapeEngine() const
411 if (mxCustomShapeEngine.is())
412 return mxCustomShapeEngine;
414 String aEngine(((SdrCustomShapeEngineItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE )).GetValue());
415 if ( !aEngine.Len() )
416 aEngine = String( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.drawing.EnhancedCustomShapeEngine" ) );
418 Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
420 Reference< XShape > aXShape = GetXShapeForSdrObject(const_cast<SdrObjCustomShape*>(this));
421 if ( aXShape.is() )
423 if ( aEngine.Len() )
425 Sequence< Any > aArgument( 1 );
426 Sequence< PropertyValue > aPropValues( 1 );
427 aPropValues[ 0 ].Name = OUString("CustomShape");
428 aPropValues[ 0 ].Value <<= aXShape;
429 aArgument[ 0 ] <<= aPropValues;
430 Reference< XInterface > xInterface( xContext->getServiceManager()->createInstanceWithArgumentsAndContext( aEngine, aArgument, xContext ) );
431 if ( xInterface.is() )
432 mxCustomShapeEngine = Reference< XCustomShapeEngine >( xInterface, UNO_QUERY );
436 return mxCustomShapeEngine;
439 const SdrObject* SdrObjCustomShape::GetSdrObjectFromCustomShape() const
441 if ( !mXRenderedCustomShape.is() )
443 Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine() );
444 if ( xCustomShapeEngine.is() )
445 ((SdrObjCustomShape*)this)->mXRenderedCustomShape = xCustomShapeEngine->render();
447 SdrObject* pRenderedCustomShape = mXRenderedCustomShape.is()
448 ? GetSdrObjectFromXShape( mXRenderedCustomShape )
449 : NULL;
450 return pRenderedCustomShape;
453 // #i37011# Shadow geometry creation
454 const SdrObject* SdrObjCustomShape::GetSdrObjectShadowFromCustomShape() const
456 if(!mpLastShadowGeometry)
458 const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
459 if(pSdrObject)
461 const SfxItemSet& rOriginalSet = GetObjectItemSet();
462 const sal_Bool bShadow(((SdrShadowItem&)rOriginalSet.Get( SDRATTR_SHADOW )).GetValue());
464 if(bShadow)
466 // create a clone with all attributes changed to shadow attributes
467 // and translation executed, too.
468 ((SdrObjCustomShape*)this)->mpLastShadowGeometry = ImpCreateShadowObjectClone(*pSdrObject, rOriginalSet);
473 return mpLastShadowGeometry;
476 sal_Bool SdrObjCustomShape::IsTextPath() const
478 const OUString sTextPath( "TextPath" );
479 sal_Bool bTextPathOn = sal_False;
480 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
481 Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath );
482 if ( pAny )
483 *pAny >>= bTextPathOn;
484 return bTextPathOn;
487 sal_Bool SdrObjCustomShape::UseNoFillStyle() const
489 sal_Bool bRet = sal_False;
490 OUString sShapeType;
491 const OUString sType( "Type" );
492 SdrCustomShapeGeometryItem& rGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
493 Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
494 if ( pAny )
495 *pAny >>= sShapeType;
496 bRet = IsCustomShapeFilledByDefault( EnhancedCustomShapeTypeNames::Get( sType ) ) == 0;
498 return bRet;
501 sal_Bool SdrObjCustomShape::IsMirroredX() const
503 sal_Bool bMirroredX = sal_False;
504 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
505 const OUString sMirroredX( "MirroredX" );
506 com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX );
507 if ( pAny )
508 *pAny >>= bMirroredX;
509 return bMirroredX;
511 sal_Bool SdrObjCustomShape::IsMirroredY() const
513 sal_Bool bMirroredY = sal_False;
514 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
515 const OUString sMirroredY( "MirroredY" );
516 com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY );
517 if ( pAny )
518 *pAny >>= bMirroredY;
519 return bMirroredY;
521 void SdrObjCustomShape::SetMirroredX( const sal_Bool bMirrorX )
523 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
524 const OUString sMirroredX( "MirroredX" );
525 PropertyValue aPropVal;
526 aPropVal.Name = sMirroredX;
527 aPropVal.Value <<= bMirrorX;
528 aGeometryItem.SetPropertyValue( aPropVal );
529 SetMergedItem( aGeometryItem );
531 void SdrObjCustomShape::SetMirroredY( const sal_Bool bMirrorY )
533 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
534 const OUString sMirroredY( "MirroredY" );
535 PropertyValue aPropVal;
536 aPropVal.Name = sMirroredY;
537 aPropVal.Value <<= bMirrorY;
538 aGeometryItem.SetPropertyValue( aPropVal );
539 SetMergedItem( aGeometryItem );
542 double SdrObjCustomShape::GetObjectRotation() const
544 return fObjectRotation;
547 bool SdrObjCustomShape::IsPostRotate() const
549 const com::sun::star::uno::Any* pAny;
550 bool bPostRotate = false;
551 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
552 pAny = rGeometryItem.GetPropertyValueByName( "IsPostRotateAngle" );
553 if ( pAny )
554 *pAny >>= bPostRotate;
555 return bPostRotate;
558 double SdrObjCustomShape::GetExtraTextRotation( const bool bPreRotation ) const
560 const com::sun::star::uno::Any* pAny;
561 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
562 const OUString sTextRotateAngle( "TextRotateAngle" );
563 const OUString sTextPreRotateAngle( "TextPreRotateAngle" );
564 pAny = rGeometryItem.GetPropertyValueByName( bPreRotation ? sTextPreRotateAngle : sTextRotateAngle );
565 double fExtraTextRotateAngle = 0.0;
566 if ( pAny )
567 *pAny >>= fExtraTextRotateAngle;
568 return fExtraTextRotateAngle;
571 sal_Bool SdrObjCustomShape::GetTextBounds( Rectangle& rTextBound ) const
573 sal_Bool bRet = sal_False;
575 Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine() );
576 if ( xCustomShapeEngine.is() )
578 awt::Rectangle aR( xCustomShapeEngine->getTextBounds() );
579 if ( aR.Width > 1 && aR.Height > 1 )
581 rTextBound = Rectangle( Point( aR.X, aR.Y ), Size( aR.Width, aR.Height ) );
582 bRet = sal_True;
585 return bRet;
587 basegfx::B2DPolyPolygon SdrObjCustomShape::GetLineGeometry( const SdrObjCustomShape* pCustomShape, const sal_Bool bBezierAllowed )
589 basegfx::B2DPolyPolygon aRetval;
590 Reference< XCustomShapeEngine > xCustomShapeEngine( pCustomShape->GetCustomShapeEngine() );
591 if ( xCustomShapeEngine.is() )
593 com::sun::star::drawing::PolyPolygonBezierCoords aBezierCoords = xCustomShapeEngine->getLineGeometry();
596 aRetval = basegfx::unotools::polyPolygonBezierToB2DPolyPolygon( aBezierCoords );
597 if ( !bBezierAllowed && aRetval.areControlPointsUsed())
599 aRetval = basegfx::tools::adaptiveSubdivideByAngle(aRetval);
602 catch ( const com::sun::star::lang::IllegalArgumentException & )
606 return aRetval;
609 std::vector< SdrCustomShapeInteraction > SdrObjCustomShape::GetInteractionHandles( const SdrObjCustomShape* pCustomShape ) const
611 std::vector< SdrCustomShapeInteraction > xRet;
614 Reference< XCustomShapeEngine > xCustomShapeEngine( pCustomShape->GetCustomShapeEngine() );
615 if ( xCustomShapeEngine.is() )
617 int i;
618 Sequence< Reference< XCustomShapeHandle > > xInteractionHandles( xCustomShapeEngine->getInteraction() );
619 for ( i = 0; i < xInteractionHandles.getLength(); i++ )
621 if ( xInteractionHandles[ i ].is() )
623 SdrCustomShapeInteraction aSdrCustomShapeInteraction;
624 aSdrCustomShapeInteraction.xInteraction = xInteractionHandles[ i ];
625 aSdrCustomShapeInteraction.aPosition = xInteractionHandles[ i ]->getPosition();
627 sal_Int32 nMode = 0;
628 switch( ImpGetCustomShapeType( *this ) )
630 case mso_sptAccentBorderCallout90 : // 2 ortho
632 if ( !i )
633 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
634 else if ( i == 1)
635 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE | CUSTOMSHAPE_HANDLE_ORTHO4;
637 break;
639 case mso_sptWedgeRectCallout :
640 case mso_sptWedgeRRectCallout :
641 case mso_sptCloudCallout :
642 case mso_sptWedgeEllipseCallout :
644 if ( !i )
645 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED;
647 break;
649 case mso_sptBorderCallout1 : // 2 diag
651 if ( !i )
652 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
653 else if ( i == 1 )
654 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE;
656 break;
657 case mso_sptBorderCallout2 : // 3
659 if ( !i )
660 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
661 else if ( i == 2 )
662 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE;
664 break;
665 case mso_sptCallout90 :
666 case mso_sptAccentCallout90 :
667 case mso_sptBorderCallout90 :
668 case mso_sptCallout1 :
669 case mso_sptCallout2 :
670 case mso_sptCallout3 :
671 case mso_sptAccentCallout1 :
672 case mso_sptAccentCallout2 :
673 case mso_sptAccentCallout3 :
674 case mso_sptBorderCallout3 :
675 case mso_sptAccentBorderCallout1 :
676 case mso_sptAccentBorderCallout2 :
677 case mso_sptAccentBorderCallout3 :
679 if ( !i )
680 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
682 break;
683 default: break;
685 aSdrCustomShapeInteraction.nMode = nMode;
686 xRet.push_back( aSdrCustomShapeInteraction );
691 catch( const uno::RuntimeException& )
694 return xRet;
697 //////////////////////////////////////////////////////////////////////////////
698 // BaseProperties section
699 #define DEFAULT_MINIMUM_SIGNED_COMPARE ((sal_Int32)0x80000000)
700 #define DEFAULT_MAXIMUM_SIGNED_COMPARE ((sal_Int32)0x7fffffff)
702 static sal_Int32 GetNumberOfProperties ( const SvxMSDffHandle* pData )
704 sal_Int32 nPropertiesNeeded=1; // position is always needed
705 sal_Int32 nFlags = pData->nFlags;
707 if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X )
708 nPropertiesNeeded++;
709 if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y )
710 nPropertiesNeeded++;
711 if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED )
712 nPropertiesNeeded++;
713 if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR )
715 nPropertiesNeeded++;
716 if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE )
718 if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
719 nPropertiesNeeded++;
720 if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
721 nPropertiesNeeded++;
724 else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE )
726 if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
727 nPropertiesNeeded++;
728 if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
729 nPropertiesNeeded++;
730 if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
731 nPropertiesNeeded++;
732 if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
733 nPropertiesNeeded++;
736 return nPropertiesNeeded;
739 static void lcl_ShapePropertiesFromDFF( const SvxMSDffHandle* pData, com::sun::star::beans::PropertyValues& rPropValues )
741 sal_Int32 nFlags = pData->nFlags, n=0;
743 // POSITION
745 const OUString sPosition( "Position" );
746 ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition;
747 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, pData->nPositionX, true, true );
748 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, pData->nPositionY, true, false );
749 rPropValues[ n ].Name = sPosition;
750 rPropValues[ n++ ].Value <<= aPosition;
752 if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X )
754 const OUString sMirroredX( "MirroredX" );
755 sal_Bool bMirroredX = sal_True;
756 rPropValues[ n ].Name = sMirroredX;
757 rPropValues[ n++ ].Value <<= bMirroredX;
759 if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y )
761 const OUString sMirroredY( "MirroredY" );
762 sal_Bool bMirroredY = sal_True;
763 rPropValues[ n ].Name = sMirroredY;
764 rPropValues[ n++ ].Value <<= bMirroredY;
766 if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED )
768 const OUString sSwitched( "Switched" );
769 sal_Bool bSwitched = sal_True;
770 rPropValues[ n ].Name = sSwitched;
771 rPropValues[ n++ ].Value <<= bSwitched;
773 if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR )
775 const OUString sPolar( "Polar" );
776 ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aCenter;
777 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.First, pData->nCenterX,
778 ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_X_IS_SPECIAL ) != 0, true );
779 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.Second, pData->nCenterY,
780 ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_Y_IS_SPECIAL ) != 0, false );
781 rPropValues[ n ].Name = sPolar;
782 rPropValues[ n++ ].Value <<= aCenter;
783 if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE )
785 if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
787 const OUString sRadiusRangeMinimum( "RadiusRangeMinimum" );
788 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
789 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, pData->nRangeXMin,
790 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, true );
791 rPropValues[ n ].Name = sRadiusRangeMinimum;
792 rPropValues[ n++ ].Value <<= aRadiusRangeMinimum;
794 if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
796 const OUString sRadiusRangeMaximum( "RadiusRangeMaximum" );
797 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
798 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, pData->nRangeXMax,
799 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, false );
800 rPropValues[ n ].Name = sRadiusRangeMaximum;
801 rPropValues[ n++ ].Value <<= aRadiusRangeMaximum;
805 else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE )
807 if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
809 const OUString sRangeXMinimum( "RangeXMinimum" );
810 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMinimum;
811 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, pData->nRangeXMin,
812 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, true );
813 rPropValues[ n ].Name = sRangeXMinimum;
814 rPropValues[ n++ ].Value <<= aRangeXMinimum;
816 if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
818 const OUString sRangeXMaximum( "RangeXMaximum" );
819 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMaximum;
820 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, pData->nRangeXMax,
821 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, false );
822 rPropValues[ n ].Name = sRangeXMaximum;
823 rPropValues[ n++ ].Value <<= aRangeXMaximum;
825 if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
827 const OUString sRangeYMinimum( "RangeYMinimum" );
828 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMinimum;
829 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, pData->nRangeYMin,
830 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MIN_IS_SPECIAL ) != 0, true );
831 rPropValues[ n ].Name = sRangeYMinimum;
832 rPropValues[ n++ ].Value <<= aRangeYMinimum;
834 if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
836 const OUString sRangeYMaximum( "RangeYMaximum" );
837 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMaximum;
838 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, pData->nRangeYMax,
839 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MAX_IS_SPECIAL ) != 0, false );
840 rPropValues[ n ].Name = sRangeYMaximum;
841 rPropValues[ n++ ].Value <<= aRangeYMaximum;
844 return;
847 sdr::properties::BaseProperties* SdrObjCustomShape::CreateObjectSpecificProperties()
849 return new sdr::properties::CustomShapeProperties(*this);
852 TYPEINIT1(SdrObjCustomShape,SdrTextObj);
853 SdrObjCustomShape::SdrObjCustomShape() :
854 SdrTextObj(),
855 fObjectRotation( 0.0 ),
856 mpLastShadowGeometry(0L)
858 bTextFrame = sal_True;
861 SdrObjCustomShape::~SdrObjCustomShape()
863 // delete buffered display geometry
864 InvalidateRenderGeometry();
867 void SdrObjCustomShape::MergeDefaultAttributes( const OUString* pType )
869 PropertyValue aPropVal;
870 OUString sShapeType;
871 const OUString sType( "Type" );
872 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
873 if ( pType && !pType->isEmpty() )
875 sal_Int32 nType = pType->toInt32();
876 if ( nType )
877 sShapeType = EnhancedCustomShapeTypeNames::Get( static_cast< MSO_SPT >( nType ) );
878 else
879 sShapeType = *pType;
881 aPropVal.Name = sType;
882 aPropVal.Value <<= sShapeType;
883 aGeometryItem.SetPropertyValue( aPropVal );
885 else
887 Any *pAny = aGeometryItem.GetPropertyValueByName( sType );
888 if ( pAny )
889 *pAny >>= sShapeType;
891 MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
893 const sal_Int32* pDefData = NULL;
894 const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
895 if ( pDefCustomShape )
896 pDefData = pDefCustomShape->pDefData;
898 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > seqAdjustmentValues;
900 //////////////////////
901 // AdjustmentValues //
902 //////////////////////
903 const OUString sAdjustmentValues( "AdjustmentValues" );
904 const Any* pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sAdjustmentValues );
905 if ( pAny )
906 *pAny >>= seqAdjustmentValues;
907 if ( pDefCustomShape && pDefData ) // now check if we have to default some adjustment values
909 // first check if there are adjustment values are to be appended
910 sal_Int32 i, nAdjustmentValues = seqAdjustmentValues.getLength();
911 sal_Int32 nAdjustmentDefaults = *pDefData++;
912 if ( nAdjustmentDefaults > nAdjustmentValues )
914 seqAdjustmentValues.realloc( nAdjustmentDefaults );
915 for ( i = nAdjustmentValues; i < nAdjustmentDefaults; i++ )
917 seqAdjustmentValues[ i ].Value <<= pDefData[ i ];
918 seqAdjustmentValues[ i ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
921 // check if there are defaulted adjustment values that should be filled the hard coded defaults (pDefValue)
922 sal_Int32 nCount = nAdjustmentValues > nAdjustmentDefaults ? nAdjustmentDefaults : nAdjustmentValues;
923 for ( i = 0; i < nCount; i++ )
925 if ( seqAdjustmentValues[ i ].State != com::sun::star::beans::PropertyState_DIRECT_VALUE )
927 seqAdjustmentValues[ i ].Value <<= pDefData[ i ];
928 seqAdjustmentValues[ i ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
932 aPropVal.Name = sAdjustmentValues;
933 aPropVal.Value <<= seqAdjustmentValues;
934 aGeometryItem.SetPropertyValue( aPropVal );
936 ///////////////
937 // Coordsize //
938 ///////////////
939 const OUString sViewBox( "ViewBox" );
940 const Any* pViewBox = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sViewBox );
941 com::sun::star::awt::Rectangle aViewBox;
942 if ( !pViewBox || !(*pViewBox >>= aViewBox ) )
944 if ( pDefCustomShape )
946 aViewBox.X = 0;
947 aViewBox.Y = 0;
948 aViewBox.Width = pDefCustomShape->nCoordWidth;
949 aViewBox.Height= pDefCustomShape->nCoordHeight;
950 aPropVal.Name = sViewBox;
951 aPropVal.Value <<= aViewBox;
952 aGeometryItem.SetPropertyValue( aPropVal );
956 const OUString sPath( "Path" );
958 //////////////////////
959 // Path/Coordinates //
960 //////////////////////
961 const OUString sCoordinates( "Coordinates" );
962 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sCoordinates );
963 if ( !pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices )
965 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates;
967 sal_Int32 i, nCount = pDefCustomShape->nVertices;
968 seqCoordinates.realloc( nCount );
969 for ( i = 0; i < nCount; i++ )
971 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates[ i ].First, pDefCustomShape->pVertices[ i ].nValA );
972 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates[ i ].Second, pDefCustomShape->pVertices[ i ].nValB );
974 aPropVal.Name = sCoordinates;
975 aPropVal.Value <<= seqCoordinates;
976 aGeometryItem.SetPropertyValue( sPath, aPropVal );
979 // Path/GluePoints //
980 const OUString sGluePoints( "GluePoints" );
981 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sGluePoints );
982 if ( !pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints )
984 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqGluePoints;
985 sal_Int32 i, nCount = pDefCustomShape->nGluePoints;
986 seqGluePoints.realloc( nCount );
987 for ( i = 0; i < nCount; i++ )
989 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA );
990 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB );
992 aPropVal.Name = sGluePoints;
993 aPropVal.Value <<= seqGluePoints;
994 aGeometryItem.SetPropertyValue( sPath, aPropVal );
997 // Path/Segments //
998 const OUString sSegments( "Segments" );
999 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sSegments );
1000 if ( !pAny && pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements )
1002 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments;
1004 sal_Int32 i, nCount = pDefCustomShape->nElements;
1005 seqSegments.realloc( nCount );
1006 for ( i = 0; i < nCount; i++ )
1008 EnhancedCustomShapeSegment& rSegInfo = seqSegments[ i ];
1009 sal_uInt16 nSDat = pDefCustomShape->pElements[ i ];
1010 lcl_ShapeSegmentFromBinary( rSegInfo, nSDat );
1012 aPropVal.Name = sSegments;
1013 aPropVal.Value <<= seqSegments;
1014 aGeometryItem.SetPropertyValue( sPath, aPropVal );
1017 // Path/StretchX //
1018 const OUString sStretchX( "StretchX" );
1019 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchX );
1020 if ( !pAny && pDefCustomShape )
1022 sal_Int32 nXRef = pDefCustomShape->nXRef;
1023 if ( ( nXRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1025 aPropVal.Name = sStretchX;
1026 aPropVal.Value <<= nXRef;
1027 aGeometryItem.SetPropertyValue( sPath, aPropVal );
1031 // Path/StretchY //
1032 const OUString sStretchY( "StretchY" );
1033 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchY );
1034 if ( !pAny && pDefCustomShape )
1036 sal_Int32 nYRef = pDefCustomShape->nYRef;
1037 if ( ( nYRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1039 aPropVal.Name = sStretchY;
1040 aPropVal.Value <<= nYRef;
1041 aGeometryItem.SetPropertyValue( sPath, aPropVal );
1045 // Path/TextFrames //
1046 const OUString sTextFrames( "TextFrames" );
1047 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sTextFrames );
1048 if ( !pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect )
1050 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > seqTextFrames;
1052 sal_Int32 i, nCount = pDefCustomShape->nTextRect;
1053 seqTextFrames.realloc( nCount );
1054 const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect;
1055 for ( i = 0; i < nCount; i++, pRectangles++ )
1057 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].TopLeft.First, pRectangles->nPairA.nValA );
1058 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].TopLeft.Second, pRectangles->nPairA.nValB );
1059 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].BottomRight.First, pRectangles->nPairB.nValA );
1060 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].BottomRight.Second, pRectangles->nPairB.nValB );
1062 aPropVal.Name = sTextFrames;
1063 aPropVal.Value <<= seqTextFrames;
1064 aGeometryItem.SetPropertyValue( sPath, aPropVal );
1067 // Equations //
1068 const OUString sEquations( "Equations" );
1069 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sEquations );
1070 if ( !pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation )
1072 com::sun::star::uno::Sequence< OUString > seqEquations;
1074 sal_Int32 i, nCount = pDefCustomShape->nCalculation;
1075 seqEquations.realloc( nCount );
1076 const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation;
1077 for ( i = 0; i < nCount; i++, pData++ )
1078 seqEquations[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] );
1079 aPropVal.Name = sEquations;
1080 aPropVal.Value <<= seqEquations;
1081 aGeometryItem.SetPropertyValue( aPropVal );
1084 // Handles //
1085 const OUString sHandles( "Handles" );
1086 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sHandles );
1087 if ( !pAny && pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
1089 com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValues > seqHandles;
1091 sal_Int32 i, nCount = pDefCustomShape->nHandles;
1092 const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
1093 seqHandles.realloc( nCount );
1094 for ( i = 0; i < nCount; i++, pData++ )
1096 sal_Int32 nPropertiesNeeded;
1097 com::sun::star::beans::PropertyValues& rPropValues = seqHandles[ i ];
1098 nPropertiesNeeded = GetNumberOfProperties( pData );
1099 rPropValues.realloc( nPropertiesNeeded );
1100 lcl_ShapePropertiesFromDFF( pData, rPropValues );
1102 aPropVal.Name = sHandles;
1103 aPropVal.Value <<= seqHandles;
1104 aGeometryItem.SetPropertyValue( aPropVal );
1106 SetMergedItem( aGeometryItem );
1109 sal_Bool SdrObjCustomShape::IsDefaultGeometry( const DefaultType eDefaultType ) const
1111 sal_Bool bIsDefaultGeometry = sal_False;
1113 PropertyValue aPropVal;
1114 OUString sShapeType;
1115 const OUString sType( "Type" );
1116 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
1118 Any *pAny = aGeometryItem.GetPropertyValueByName( sType );
1119 if ( pAny )
1120 *pAny >>= sShapeType;
1122 MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
1124 const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
1125 const OUString sPath( "Path" );
1126 switch( eDefaultType )
1128 case DEFAULT_VIEWBOX :
1130 const OUString sViewBox( "ViewBox" );
1131 const Any* pViewBox = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sViewBox );
1132 com::sun::star::awt::Rectangle aViewBox;
1133 if ( pViewBox && ( *pViewBox >>= aViewBox ) )
1135 if ( ( aViewBox.Width == pDefCustomShape->nCoordWidth )
1136 && ( aViewBox.Height == pDefCustomShape->nCoordHeight ) )
1137 bIsDefaultGeometry = sal_True;
1140 break;
1142 case DEFAULT_PATH :
1144 const OUString sCoordinates( "Coordinates" );
1145 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sCoordinates );
1146 if ( pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices )
1148 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates1, seqCoordinates2;
1149 if ( *pAny >>= seqCoordinates1 )
1151 sal_Int32 i, nCount = pDefCustomShape->nVertices;
1152 seqCoordinates2.realloc( nCount );
1153 for ( i = 0; i < nCount; i++ )
1155 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ i ].First, pDefCustomShape->pVertices[ i ].nValA );
1156 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ i ].Second, pDefCustomShape->pVertices[ i ].nValB );
1158 if ( seqCoordinates1 == seqCoordinates2 )
1159 bIsDefaultGeometry = sal_True;
1162 else if ( pDefCustomShape && ( ( pDefCustomShape->nVertices == 0 ) || ( pDefCustomShape->pVertices == 0 ) ) )
1163 bIsDefaultGeometry = sal_True;
1165 break;
1167 case DEFAULT_GLUEPOINTS :
1169 const OUString sGluePoints( "GluePoints" );
1170 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sGluePoints );
1171 if ( pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints )
1173 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqGluePoints1, seqGluePoints2;
1174 if ( *pAny >>= seqGluePoints1 )
1176 sal_Int32 i, nCount = pDefCustomShape->nGluePoints;
1177 seqGluePoints2.realloc( nCount );
1178 for ( i = 0; i < nCount; i++ )
1180 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints2[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA );
1181 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints2[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB );
1183 if ( seqGluePoints1 == seqGluePoints2 )
1184 bIsDefaultGeometry = sal_True;
1187 else if ( pDefCustomShape && ( pDefCustomShape->nGluePoints == 0 ) )
1188 bIsDefaultGeometry = sal_True;
1190 break;
1192 case DEFAULT_SEGMENTS :
1194 // Path/Segments //
1195 const OUString sSegments( "Segments" );
1196 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sSegments );
1197 if ( pAny )
1199 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments1, seqSegments2;
1200 if ( *pAny >>= seqSegments1 )
1202 if ( pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements )
1204 sal_Int32 i, nCount = pDefCustomShape->nElements;
1205 if ( nCount )
1207 seqSegments2.realloc( nCount );
1208 for ( i = 0; i < nCount; i++ )
1210 EnhancedCustomShapeSegment& rSegInfo = seqSegments2[ i ];
1211 sal_uInt16 nSDat = pDefCustomShape->pElements[ i ];
1212 lcl_ShapeSegmentFromBinary( rSegInfo, nSDat );
1214 if ( seqSegments1 == seqSegments2 )
1215 bIsDefaultGeometry = sal_True;
1218 else
1220 // check if its the default segment description ( M L Z N )
1221 if ( seqSegments1.getLength() == 4 )
1223 if ( ( seqSegments1[ 0 ].Command == EnhancedCustomShapeSegmentCommand::MOVETO )
1224 && ( seqSegments1[ 1 ].Command == EnhancedCustomShapeSegmentCommand::LINETO )
1225 && ( seqSegments1[ 2 ].Command == EnhancedCustomShapeSegmentCommand::CLOSESUBPATH )
1226 && ( seqSegments1[ 3 ].Command == EnhancedCustomShapeSegmentCommand::ENDSUBPATH ) )
1227 bIsDefaultGeometry = sal_True;
1232 else if ( pDefCustomShape && ( ( pDefCustomShape->nElements == 0 ) || ( pDefCustomShape->pElements == 0 ) ) )
1233 bIsDefaultGeometry = sal_True;
1235 break;
1237 case DEFAULT_STRETCHX :
1239 const OUString sStretchX( "StretchX" );
1240 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchX );
1241 if ( pAny && pDefCustomShape )
1243 sal_Int32 nStretchX = 0;
1244 if ( *pAny >>= nStretchX )
1246 if ( pDefCustomShape->nXRef == nStretchX )
1247 bIsDefaultGeometry = sal_True;
1250 else if ( pDefCustomShape && ( pDefCustomShape->nXRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1251 bIsDefaultGeometry = sal_True;
1253 break;
1255 case DEFAULT_STRETCHY :
1257 const OUString sStretchY( "StretchY" );
1258 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchY );
1259 if ( pAny && pDefCustomShape )
1261 sal_Int32 nStretchY = 0;
1262 if ( *pAny >>= nStretchY )
1264 if ( pDefCustomShape->nYRef == nStretchY )
1265 bIsDefaultGeometry = sal_True;
1268 else if ( pDefCustomShape && ( pDefCustomShape->nYRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1269 bIsDefaultGeometry = sal_True;
1271 break;
1273 case DEFAULT_EQUATIONS :
1275 const OUString sEquations( "Equations" );
1276 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sEquations );
1277 if ( pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation )
1279 com::sun::star::uno::Sequence< OUString > seqEquations1, seqEquations2;
1280 if ( *pAny >>= seqEquations1 )
1282 sal_Int32 i, nCount = pDefCustomShape->nCalculation;
1283 seqEquations2.realloc( nCount );
1285 const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation;
1286 for ( i = 0; i < nCount; i++, pData++ )
1287 seqEquations2[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] );
1289 if ( seqEquations1 == seqEquations2 )
1290 bIsDefaultGeometry = sal_True;
1293 else if ( pDefCustomShape && ( ( pDefCustomShape->nCalculation == 0 ) || ( pDefCustomShape->pCalculation == 0 ) ) )
1294 bIsDefaultGeometry = sal_True;
1296 break;
1298 case DEFAULT_TEXTFRAMES :
1300 const OUString sTextFrames( "TextFrames" );
1301 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sTextFrames );
1302 if ( pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect )
1304 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > seqTextFrames1, seqTextFrames2;
1305 if ( *pAny >>= seqTextFrames1 )
1307 sal_Int32 i, nCount = pDefCustomShape->nTextRect;
1308 seqTextFrames2.realloc( nCount );
1309 const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect;
1310 for ( i = 0; i < nCount; i++, pRectangles++ )
1312 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].TopLeft.First, pRectangles->nPairA.nValA );
1313 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].TopLeft.Second, pRectangles->nPairA.nValB );
1314 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].BottomRight.First, pRectangles->nPairB.nValA );
1315 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].BottomRight.Second, pRectangles->nPairB.nValB );
1317 if ( seqTextFrames1 == seqTextFrames2 )
1318 bIsDefaultGeometry = sal_True;
1321 else if ( pDefCustomShape && ( ( pDefCustomShape->nTextRect == 0 ) || ( pDefCustomShape->pTextRect == 0 ) ) )
1322 bIsDefaultGeometry = sal_True;
1324 break;
1326 case DEFAULT_HANDLES :
1328 const OUString sHandles( "Handles" );
1329 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sHandles );
1330 if ( pAny && pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
1332 com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValues > seqHandles1, seqHandles2;
1333 if ( *pAny >>= seqHandles1 )
1335 sal_Int32 i, nCount = pDefCustomShape->nHandles;
1336 const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
1337 seqHandles2.realloc( nCount );
1338 for ( i = 0; i < nCount; i++, pData++ )
1340 sal_Int32 nPropertiesNeeded;
1341 com::sun::star::beans::PropertyValues& rPropValues = seqHandles2[ i ];
1342 nPropertiesNeeded = GetNumberOfProperties( pData );
1343 rPropValues.realloc( nPropertiesNeeded );
1344 lcl_ShapePropertiesFromDFF( pData, rPropValues );
1346 if ( seqHandles1 == seqHandles2 )
1347 bIsDefaultGeometry = sal_True;
1350 else if ( pDefCustomShape && ( ( pDefCustomShape->nHandles == 0 ) || ( pDefCustomShape->pHandles == 0 ) ) )
1351 bIsDefaultGeometry = sal_True;
1353 break;
1355 return bIsDefaultGeometry;
1358 void SdrObjCustomShape::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
1360 rInfo.bResizeFreeAllowed=fObjectRotation == 0.0;
1361 rInfo.bResizePropAllowed=sal_True;
1362 rInfo.bRotateFreeAllowed=sal_True;
1363 rInfo.bRotate90Allowed =sal_True;
1364 rInfo.bMirrorFreeAllowed=sal_True;
1365 rInfo.bMirror45Allowed =sal_True;
1366 rInfo.bMirror90Allowed =sal_True;
1367 rInfo.bTransparenceAllowed = sal_False;
1368 rInfo.bGradientAllowed = sal_False;
1369 rInfo.bShearAllowed =sal_True;
1370 rInfo.bEdgeRadiusAllowed=sal_False;
1371 rInfo.bNoContortion =sal_True;
1373 // #i37011#
1374 if ( mXRenderedCustomShape.is() )
1376 const SdrObject* pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape );
1377 if ( pRenderedCustomShape )
1379 // #i37262#
1380 // Iterate self over the contained objects, since there are combinations of
1381 // polygon and curve objects. In that case, aInfo.bCanConvToPath and
1382 // aInfo.bCanConvToPoly would be false. What is needed here is an or, not an and.
1383 SdrObjListIter aIterator(*pRenderedCustomShape);
1384 while(aIterator.IsMore())
1386 SdrObject* pCandidate = aIterator.Next();
1387 SdrObjTransformInfoRec aInfo;
1388 pCandidate->TakeObjInfo(aInfo);
1390 // set path and poly conversion if one is possible since
1391 // this object will first be broken
1392 const bool bCanConvToPathOrPoly(aInfo.bCanConvToPath || aInfo.bCanConvToPoly);
1393 if(rInfo.bCanConvToPath != bCanConvToPathOrPoly)
1395 rInfo.bCanConvToPath = bCanConvToPathOrPoly;
1398 if(rInfo.bCanConvToPoly != bCanConvToPathOrPoly)
1400 rInfo.bCanConvToPoly = bCanConvToPathOrPoly;
1403 if(rInfo.bCanConvToContour != aInfo.bCanConvToContour)
1405 rInfo.bCanConvToContour = aInfo.bCanConvToContour;
1408 if(rInfo.bShearAllowed != aInfo.bShearAllowed)
1410 rInfo.bShearAllowed = aInfo.bShearAllowed;
1417 void SdrObjCustomShape::SetModel(SdrModel* pNewModel)
1419 SdrTextObj::SetModel(pNewModel);
1420 mXRenderedCustomShape.clear();
1423 sal_uInt16 SdrObjCustomShape::GetObjIdentifier() const
1425 return sal_uInt16(OBJ_CUSTOMSHAPE);
1428 ////////////////////////////////////////////////////////////////////////////////////////////////////
1430 void SdrObjCustomShape::RecalcSnapRect()
1432 SdrTextObj::RecalcSnapRect();
1434 const Rectangle& SdrObjCustomShape::GetSnapRect() const
1436 return SdrTextObj::GetSnapRect();
1438 const Rectangle& SdrObjCustomShape::GetCurrentBoundRect() const
1440 return SdrTextObj::GetCurrentBoundRect();
1442 const Rectangle& SdrObjCustomShape::GetLogicRect() const
1444 return SdrTextObj::GetLogicRect();
1446 void SdrObjCustomShape::NbcSetSnapRect( const Rectangle& rRect )
1448 aRect=rRect;
1449 ImpJustifyRect(aRect);
1450 InvalidateRenderGeometry();
1451 Rectangle aTextBound( aRect );
1452 if ( GetTextBounds( aTextBound ) )
1454 if ( pModel==NULL || !pModel->IsPasteResize() )
1456 long nHDist=GetTextLeftDistance()+GetTextRightDistance();
1457 long nVDist=GetTextUpperDistance()+GetTextLowerDistance();
1458 long nTWdt=aTextBound.GetWidth ()-1-nHDist; if (nTWdt<0) nTWdt=0;
1459 long nTHgt=aTextBound.GetHeight()-1-nVDist; if (nTHgt<0) nTHgt=0;
1460 if ( IsAutoGrowWidth() )
1461 NbcSetMinTextFrameWidth( nTWdt );
1462 if ( IsAutoGrowHeight() )
1463 NbcSetMinTextFrameHeight( nTHgt );
1464 NbcAdjustTextFrameWidthAndHeight();
1467 ImpCheckShear();
1468 SetRectsDirty();
1469 SetChanged();
1471 void SdrObjCustomShape::SetSnapRect( const Rectangle& rRect )
1473 Rectangle aBoundRect0;
1474 if ( pUserCall )
1475 aBoundRect0 = GetLastBoundRect();
1476 NbcSetSnapRect( rRect );
1477 BroadcastObjectChange();
1478 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
1480 void SdrObjCustomShape::NbcSetLogicRect( const Rectangle& rRect )
1482 aRect = rRect;
1483 ImpJustifyRect( aRect );
1484 InvalidateRenderGeometry();
1485 Rectangle aTextBound( aRect );
1486 if ( GetTextBounds( aTextBound ) )
1488 long nHDist=GetTextLeftDistance()+GetTextRightDistance();
1489 long nVDist=GetTextUpperDistance()+GetTextLowerDistance();
1491 long nTWdt=aTextBound.GetWidth()-1-nHDist; if (nTWdt<0) nTWdt=0;
1492 long nTHgt=aTextBound.GetHeight()-1-nVDist; if (nTHgt<0) nTHgt=0;
1493 if ( IsAutoGrowWidth() )
1494 NbcSetMinTextFrameWidth( nTWdt );
1495 if ( IsAutoGrowHeight() )
1496 NbcSetMinTextFrameHeight( nTHgt );
1497 NbcAdjustTextFrameWidthAndHeight();
1499 SetRectsDirty();
1500 SetChanged();
1502 void SdrObjCustomShape::SetLogicRect( const Rectangle& rRect )
1504 Rectangle aBoundRect0;
1505 if ( pUserCall )
1506 aBoundRect0 = GetLastBoundRect();
1507 NbcSetLogicRect(rRect);
1508 BroadcastObjectChange();
1509 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
1511 void SdrObjCustomShape::Move( const Size& rSiz )
1513 if ( rSiz.Width() || rSiz.Height() )
1515 Rectangle aBoundRect0;
1516 if ( pUserCall )
1517 aBoundRect0 = GetLastBoundRect();
1518 NbcMove(rSiz);
1519 SetChanged();
1520 BroadcastObjectChange();
1521 SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0);
1524 void SdrObjCustomShape::NbcMove( const Size& rSiz )
1526 SdrTextObj::NbcMove( rSiz );
1527 if ( mXRenderedCustomShape.is() )
1529 SdrObject* pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape );
1530 if ( pRenderedCustomShape )
1532 // #i97149# the visualisation shape needs to be informed
1533 // about change, too
1534 pRenderedCustomShape->ActionChanged();
1535 pRenderedCustomShape->NbcMove( rSiz );
1539 // #i37011# adapt geometry shadow
1540 if(mpLastShadowGeometry)
1542 mpLastShadowGeometry->NbcMove( rSiz );
1545 void SdrObjCustomShape::Resize( const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bUnsetRelative )
1547 SdrTextObj::Resize( rRef, xFact, yFact, bUnsetRelative );
1550 void SdrObjCustomShape::NbcResize( const Point& rRef, const Fraction& rxFact, const Fraction& ryFact )
1552 Fraction xFact( rxFact );
1553 Fraction yFact( ryFact );
1555 // taking care of handles that should not been changed
1556 Rectangle aOld( aRect );
1557 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
1559 SdrTextObj::NbcResize( rRef, xFact, yFact );
1561 if ( ( xFact.GetNumerator() != xFact.GetDenominator() )
1562 || ( yFact.GetNumerator()!= yFact.GetDenominator() ) )
1564 if ( ( ( xFact.GetNumerator() < 0 ) && ( xFact.GetDenominator() > 0 ) ) ||
1565 ( ( xFact.GetNumerator() > 0 ) && ( xFact.GetDenominator() < 0 ) ) )
1567 SetMirroredX( IsMirroredX() == sal_False );
1569 if ( ( ( yFact.GetNumerator() < 0 ) && ( yFact.GetDenominator() > 0 ) ) ||
1570 ( ( yFact.GetNumerator() > 0 ) && ( yFact.GetDenominator() < 0 ) ) )
1572 SetMirroredY( IsMirroredY() == sal_False );
1576 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd( aInteractionHandles.end() );
1577 aIter != aEnd; ++aIter )
1581 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
1582 aIter->xInteraction->setControllerPosition( aIter->aPosition );
1583 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X )
1585 sal_Int32 nX = ( aIter->aPosition.X - aOld.Left() ) + aRect.Left();
1586 aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( nX, aIter->xInteraction->getPosition().Y ) );
1588 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y )
1590 sal_Int32 nY = ( aIter->aPosition.Y - aOld.Top() ) + aRect.Top();
1591 aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( aIter->xInteraction->getPosition().X, nY ) );
1594 catch ( const uno::RuntimeException& )
1598 InvalidateRenderGeometry();
1600 void SdrObjCustomShape::NbcRotate( const Point& rRef, long nWink, double sn, double cs )
1602 sal_Bool bMirroredX = IsMirroredX();
1603 sal_Bool bMirroredY = IsMirroredY();
1605 fObjectRotation = fmod( fObjectRotation, 360.0 );
1606 if ( fObjectRotation < 0 )
1607 fObjectRotation = 360 + fObjectRotation;
1609 // the rotation angle for ashapes is stored in fObjectRotation, this rotation
1610 // has to be applied to the text object (which is internally using aGeo.nWink).
1611 SdrTextObj::NbcRotate( aRect.TopLeft(), -aGeo.nDrehWink, // retrieving the unrotated text object
1612 sin( (-aGeo.nDrehWink) * F_PI18000 ),
1613 cos( (-aGeo.nDrehWink) * F_PI18000 ) );
1614 aGeo.nDrehWink = 0; // resetting aGeo data
1615 aGeo.RecalcSinCos();
1617 long nW = (long)( fObjectRotation * 100 ); // applying our object rotation
1618 if ( bMirroredX )
1619 nW = 36000 - nW;
1620 if ( bMirroredY )
1621 nW = 18000 - nW;
1622 nW = nW % 36000;
1623 if ( nW < 0 )
1624 nW = 36000 + nW;
1625 SdrTextObj::NbcRotate( aRect.TopLeft(), nW, // applying text rotation
1626 sin( nW * F_PI18000 ),
1627 cos( nW * F_PI18000 ) );
1629 int nSwap = 0;
1630 if ( bMirroredX )
1631 nSwap ^= 1;
1632 if ( bMirroredY )
1633 nSwap ^= 1;
1635 double fWink = nWink; // updating to our new object rotation
1636 fWink /= 100.0;
1637 fObjectRotation = fmod( nSwap ? fObjectRotation - fWink : fObjectRotation + fWink, 360.0 );
1638 if ( fObjectRotation < 0 )
1639 fObjectRotation = 360 + fObjectRotation;
1641 SdrTextObj::NbcRotate( rRef, nWink, sn, cs ); // applying text rotation
1642 InvalidateRenderGeometry();
1645 void SdrObjCustomShape::NbcMirror( const Point& rRef1, const Point& rRef2 )
1647 // storing horizontal and vertical flipping without modifying the rotate angle
1648 sal_Bool bHorz = sal_False;
1649 sal_Bool bVert = sal_False;
1650 if ( rRef1.X() == rRef2.X() )
1651 bHorz = sal_True;
1652 if ( rRef1.Y() == rRef2.Y() )
1653 bVert = sal_True;
1654 if ( !bHorz && !bVert )
1655 bHorz = bVert = sal_True;
1657 if ( bHorz || bVert )
1659 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
1661 // "MirroredX" //
1662 if ( bHorz )
1664 const OUString sMirroredX( "MirroredX" );
1665 com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX );
1666 if ( pAny )
1668 sal_Bool bFlip = sal_Bool();
1669 if ( *pAny >>= bFlip )
1671 if ( bFlip )
1672 bHorz = sal_False;
1675 PropertyValue aPropVal;
1676 aPropVal.Name = sMirroredX;
1677 aPropVal.Value <<= bHorz;
1678 aGeometryItem.SetPropertyValue( aPropVal );
1681 // "MirroredY" //
1682 if ( bVert )
1684 const OUString sMirroredY( "MirroredY" );
1685 com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY );
1686 if ( pAny )
1688 sal_Bool bFlip = sal_Bool();
1689 if ( *pAny >>= bFlip )
1691 if ( bFlip )
1692 bVert = sal_False;
1695 PropertyValue aPropVal;
1696 aPropVal.Name = sMirroredY;
1697 aPropVal.Value <<= bVert;
1698 aGeometryItem.SetPropertyValue( aPropVal );
1700 SetMergedItem( aGeometryItem );
1702 SdrTextObj::NbcMirror( rRef1, rRef2 );
1703 InvalidateRenderGeometry();
1706 void SdrObjCustomShape::Shear( const Point& rRef, long nWink, double tn, bool bVShear )
1708 SdrTextObj::Shear( rRef, nWink, tn, bVShear );
1709 InvalidateRenderGeometry();
1711 void SdrObjCustomShape::NbcShear( const Point& rRef, long nWink, double tn, bool bVShear )
1713 long nDrehWink = aGeo.nDrehWink;
1714 if ( nDrehWink )
1716 aGeo.nDrehWink = -nDrehWink;
1717 aGeo.RecalcSinCos();
1718 NbcRotate( rRef, aGeo.nDrehWink, aGeo.nSin, aGeo.nCos );
1720 SdrTextObj::NbcShear(rRef,nWink,tn,bVShear);
1721 if ( nDrehWink )
1723 aGeo.nDrehWink = nDrehWink;
1724 aGeo.RecalcSinCos();
1725 Rotate( rRef, aGeo.nDrehWink, aGeo.nSin, aGeo.nCos );
1727 InvalidateRenderGeometry();
1730 ////////////////////////////////////////////////////////////////////////////////////////////////////
1732 SdrGluePoint SdrObjCustomShape::GetVertexGluePoint(sal_uInt16 nPosNum) const
1734 sal_Int32 nWdt = ImpGetLineWdt(); // #i25616#
1736 // #i25616#
1737 if(!LineIsOutsideGeometry())
1739 nWdt++;
1740 nWdt /= 2;
1743 Point aPt;
1744 switch (nPosNum) {
1745 case 0: aPt=aRect.TopCenter(); aPt.Y()-=nWdt; break;
1746 case 1: aPt=aRect.RightCenter(); aPt.X()+=nWdt; break;
1747 case 2: aPt=aRect.BottomCenter(); aPt.Y()+=nWdt; break;
1748 case 3: aPt=aRect.LeftCenter(); aPt.X()-=nWdt; break;
1750 if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan);
1751 if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1752 aPt-=GetSnapRect().Center();
1753 SdrGluePoint aGP(aPt);
1754 aGP.SetPercent(sal_False);
1755 return aGP;
1758 ////////////////////////////////////////////////////////////////////////////////////////////////////
1760 // #i38892#
1761 void SdrObjCustomShape::ImpCheckCustomGluePointsAreAdded()
1763 const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
1765 if(pSdrObject)
1767 const SdrGluePointList* pSource = pSdrObject->GetGluePointList();
1769 if(pSource && pSource->GetCount())
1771 if(!SdrTextObj::GetGluePointList())
1773 SdrTextObj::ForceGluePointList();
1776 const SdrGluePointList* pList = SdrTextObj::GetGluePointList();
1778 if(pList)
1780 SdrGluePointList aNewList;
1781 sal_uInt16 a;
1783 for(a = 0; a < pSource->GetCount(); a++)
1785 SdrGluePoint aCopy((*pSource)[a]);
1786 aCopy.SetUserDefined(sal_False);
1787 aNewList.Insert(aCopy);
1790 sal_Bool bMirroredX = IsMirroredX();
1791 sal_Bool bMirroredY = IsMirroredY();
1793 long nShearWink = aGeo.nShearWink;
1794 double fTan = aGeo.nTan;
1796 if ( aGeo.nDrehWink || nShearWink || bMirroredX || bMirroredY )
1798 Polygon aPoly( aRect );
1799 if( nShearWink )
1801 sal_uInt16 nPointCount=aPoly.GetSize();
1802 for (sal_uInt16 i=0; i<nPointCount; i++)
1803 ShearPoint(aPoly[i],aRect.Center(), fTan, sal_False );
1805 if ( aGeo.nDrehWink )
1806 aPoly.Rotate( aRect.Center(), aGeo.nDrehWink / 10 );
1808 Rectangle aBoundRect( aPoly.GetBoundRect() );
1809 sal_Int32 nXDiff = aBoundRect.Left() - aRect.Left();
1810 sal_Int32 nYDiff = aBoundRect.Top() - aRect.Top();
1812 if (nShearWink&&((bMirroredX&&!bMirroredY)||(bMirroredY&&!bMirroredX)))
1814 nShearWink = -nShearWink;
1815 fTan = -fTan;
1818 Point aRef( aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
1819 for ( a = 0; a < aNewList.GetCount(); a++ )
1821 SdrGluePoint& rPoint = aNewList[ a ];
1822 Point aGlue( rPoint.GetPos() );
1823 if ( nShearWink )
1824 ShearPoint( aGlue, aRef, fTan );
1826 RotatePoint( aGlue, aRef, sin( fObjectRotation * F_PI180 ), cos( fObjectRotation * F_PI180 ) );
1827 if ( bMirroredX )
1828 aGlue.X() = aRect.GetWidth() - aGlue.X();
1829 if ( bMirroredY )
1830 aGlue.Y() = aRect.GetHeight() - aGlue.Y();
1831 aGlue.X() -= nXDiff;
1832 aGlue.Y() -= nYDiff;
1833 rPoint.SetPos( aGlue );
1837 for(a = 0; a < pList->GetCount(); a++)
1839 const SdrGluePoint& rCandidate = (*pList)[a];
1841 if(rCandidate.IsUserDefined())
1843 aNewList.Insert(rCandidate);
1847 // copy new list to local. This is NOT very convenient behavior, the local
1848 // GluePointList should not be set, but we delivered by using GetGluePointList(),
1849 // maybe on demand. Since the local object is changed here, this is assumed to
1850 // be a result of GetGluePointList and thus the list is copied
1851 if(pPlusData)
1853 pPlusData->SetGluePoints(aNewList);
1860 // #i38892#
1861 const SdrGluePointList* SdrObjCustomShape::GetGluePointList() const
1863 ((SdrObjCustomShape*)this)->ImpCheckCustomGluePointsAreAdded();
1864 return SdrTextObj::GetGluePointList();
1867 // #i38892#
1868 SdrGluePointList* SdrObjCustomShape::ForceGluePointList()
1870 if(SdrTextObj::ForceGluePointList())
1872 ImpCheckCustomGluePointsAreAdded();
1873 return SdrTextObj::ForceGluePointList();
1875 else
1877 return 0L;
1881 ////////////////////////////////////////////////////////////////////////////////////////////////////
1883 sal_uInt32 SdrObjCustomShape::GetHdlCount() const
1885 const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount());
1886 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
1887 return ( aInteractionHandles.size() + nBasicHdlCount );
1890 SdrHdl* SdrObjCustomShape::GetHdl( sal_uInt32 nHdlNum ) const
1892 SdrHdl* pH = NULL;
1893 const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount());
1895 if ( nHdlNum < nBasicHdlCount )
1896 pH = SdrTextObj::GetHdl( nHdlNum );
1897 else
1899 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
1900 const sal_uInt32 nCustomShapeHdlNum(nHdlNum - nBasicHdlCount);
1902 if ( nCustomShapeHdlNum < aInteractionHandles.size() )
1904 if ( aInteractionHandles[ nCustomShapeHdlNum ].xInteraction.is() )
1908 com::sun::star::awt::Point aPosition( aInteractionHandles[ nCustomShapeHdlNum ].xInteraction->getPosition() );
1909 pH = new SdrHdl( Point( aPosition.X, aPosition.Y ), HDL_CUSTOMSHAPE1 );
1910 pH->SetPointNum( nCustomShapeHdlNum );
1911 pH->SetObj( (SdrObject*)this );
1913 catch ( const uno::RuntimeException& )
1919 return pH;
1922 ////////////////////////////////////////////////////////////////////////////////////////////////////
1924 bool SdrObjCustomShape::hasSpecialDrag() const
1926 return true;
1929 bool SdrObjCustomShape::beginSpecialDrag(SdrDragStat& rDrag) const
1931 const SdrHdl* pHdl = rDrag.GetHdl();
1933 if(pHdl && HDL_CUSTOMSHAPE1 == pHdl->GetKind())
1935 rDrag.SetEndDragChangesAttributes(true);
1936 rDrag.SetNoSnap(true);
1938 else
1940 const SdrHdl* pHdl2 = rDrag.GetHdl();
1941 const SdrHdlKind eHdl((pHdl2 == NULL) ? HDL_MOVE : pHdl2->GetKind());
1943 switch( eHdl )
1945 case HDL_UPLFT :
1946 case HDL_UPPER :
1947 case HDL_UPRGT :
1948 case HDL_LEFT :
1949 case HDL_RIGHT :
1950 case HDL_LWLFT :
1951 case HDL_LOWER :
1952 case HDL_LWRGT :
1953 case HDL_MOVE :
1955 break;
1957 default:
1959 return false;
1964 return true;
1967 void SdrObjCustomShape::DragResizeCustomShape( const Rectangle& rNewRect, SdrObjCustomShape* pObj ) const
1969 Rectangle aOld( pObj->aRect );
1970 sal_Bool bOldMirroredX( pObj->IsMirroredX() );
1971 sal_Bool bOldMirroredY( pObj->IsMirroredY() );
1973 Rectangle aNewRect( rNewRect );
1974 aNewRect.Justify();
1976 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( pObj ) );
1978 GeoStat aGeoStat( pObj->GetGeoStat() );
1979 if ( aNewRect.TopLeft()!= pObj->aRect.TopLeft() &&
1980 ( pObj->aGeo.nDrehWink || pObj->aGeo.nShearWink ) )
1982 Point aNewPos( aNewRect.TopLeft() );
1983 if ( pObj->aGeo.nShearWink ) ShearPoint( aNewPos, aOld.TopLeft(), aGeoStat.nTan );
1984 if ( pObj->aGeo.nDrehWink ) RotatePoint(aNewPos, aOld.TopLeft(), aGeoStat.nSin, aGeoStat.nCos );
1985 aNewRect.SetPos( aNewPos );
1987 if ( aNewRect != pObj->aRect )
1989 pObj->SetLogicRect( aNewRect );
1990 pObj->InvalidateRenderGeometry();
1992 if ( rNewRect.Left() > rNewRect.Right() )
1994 Point aTop( ( pObj->GetSnapRect().Left() + pObj->GetSnapRect().Right() ) >> 1, pObj->GetSnapRect().Top() );
1995 Point aBottom( aTop.X(), aTop.Y() + 1000 );
1996 pObj->NbcMirror( aTop, aBottom );
1998 if ( rNewRect.Top() > rNewRect.Bottom() )
2000 Point aLeft( pObj->GetSnapRect().Left(), ( pObj->GetSnapRect().Top() + pObj->GetSnapRect().Bottom() ) >> 1 );
2001 Point aRight( aLeft.X() + 1000, aLeft.Y() );
2002 pObj->NbcMirror( aLeft, aRight );
2005 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd( aInteractionHandles.end() );
2006 aIter != aEnd ; ++aIter )
2010 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2011 aIter->xInteraction->setControllerPosition( aIter->aPosition );
2012 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X )
2014 sal_Int32 nX;
2015 if ( bOldMirroredX )
2017 nX = ( aIter->aPosition.X - aOld.Right() );
2018 if ( rNewRect.Left() > rNewRect.Right() )
2019 nX = pObj->aRect.Left() - nX;
2020 else
2021 nX += pObj->aRect.Right();
2023 else
2025 nX = ( aIter->aPosition.X - aOld.Left() );
2026 if ( rNewRect.Left() > rNewRect.Right() )
2027 nX = pObj->aRect.Right() - nX;
2028 else
2029 nX += pObj->aRect.Left();
2031 aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( nX, aIter->xInteraction->getPosition().Y ) );
2033 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y )
2035 sal_Int32 nY;
2036 if ( bOldMirroredY )
2038 nY = ( aIter->aPosition.Y - aOld.Bottom() );
2039 if ( rNewRect.Top() > rNewRect.Bottom() )
2040 nY = pObj->aRect.Top() - nY;
2041 else
2042 nY += pObj->aRect.Bottom();
2044 else
2046 nY = ( aIter->aPosition.Y - aOld.Top() );
2047 if ( rNewRect.Top() > rNewRect.Bottom() )
2048 nY = pObj->aRect.Bottom() - nY;
2049 else
2050 nY += pObj->aRect.Top();
2052 aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( aIter->xInteraction->getPosition().X, nY ) );
2055 catch ( const uno::RuntimeException& )
2062 void SdrObjCustomShape::DragMoveCustomShapeHdl( const Point aDestination, const sal_uInt16 nCustomShapeHdlNum, SdrObjCustomShape* pObj ) const
2064 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( pObj ) );
2065 if ( nCustomShapeHdlNum < aInteractionHandles.size() )
2067 SdrCustomShapeInteraction aInteractionHandle( aInteractionHandles[ nCustomShapeHdlNum ] );
2068 if ( aInteractionHandle.xInteraction.is() )
2072 com::sun::star::awt::Point aPt( aDestination.X(), aDestination.Y() );
2073 if ( aInteractionHandle.nMode & CUSTOMSHAPE_HANDLE_MOVE_SHAPE )
2075 sal_Int32 nXDiff = aPt.X - aInteractionHandle.aPosition.X;
2076 sal_Int32 nYDiff = aPt.Y - aInteractionHandle.aPosition.Y;
2078 pObj->aRect.Move( nXDiff, nYDiff );
2079 pObj->aOutRect.Move( nXDiff, nYDiff );
2080 pObj->maSnapRect.Move( nXDiff, nYDiff );
2081 pObj->SetRectsDirty(sal_True);
2082 pObj->InvalidateRenderGeometry();
2084 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd( aInteractionHandles.end() ) ;
2085 aIter != aEnd; ++aIter)
2087 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2089 if ( aIter->xInteraction.is() )
2090 aIter->xInteraction->setControllerPosition( aIter->aPosition );
2094 aInteractionHandle.xInteraction->setControllerPosition( aPt );
2096 catch ( const uno::RuntimeException& )
2103 bool SdrObjCustomShape::applySpecialDrag(SdrDragStat& rDrag)
2105 const SdrHdl* pHdl = rDrag.GetHdl();
2106 const SdrHdlKind eHdl((pHdl == NULL) ? HDL_MOVE : pHdl->GetKind());
2108 switch(eHdl)
2110 case HDL_CUSTOMSHAPE1 :
2112 rDrag.SetEndDragChangesGeoAndAttributes(true);
2113 DragMoveCustomShapeHdl( rDrag.GetNow(), (sal_uInt16)pHdl->GetPointNum(), this );
2114 SetRectsDirty();
2115 InvalidateRenderGeometry();
2116 SetChanged();
2117 break;
2120 case HDL_UPLFT :
2121 case HDL_UPPER :
2122 case HDL_UPRGT :
2123 case HDL_LEFT :
2124 case HDL_RIGHT :
2125 case HDL_LWLFT :
2126 case HDL_LOWER :
2127 case HDL_LWRGT :
2129 DragResizeCustomShape(ImpDragCalcRect(rDrag), this);
2130 break;
2132 case HDL_MOVE :
2134 Move(Size(rDrag.GetDX(), rDrag.GetDY()));
2135 break;
2137 default: break;
2140 return true;
2143 ////////////////////////////////////////////////////////////////////////////////////////////////////
2145 void SdrObjCustomShape::DragCreateObject( SdrDragStat& rStat )
2147 Rectangle aRect1;
2148 rStat.TakeCreateRect( aRect1 );
2150 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
2152 sal_uInt32 nDefaultObjectSizeWidth = 3000; // default width from SDOptions ?
2153 sal_uInt32 nDefaultObjectSizeHeight= 3000;
2155 if ( ImpVerticalSwitch( *this ) )
2157 SetMirroredX( aRect1.Left() > aRect1.Right() );
2159 aRect1 = Rectangle( rStat.GetNow(), Size( nDefaultObjectSizeWidth, nDefaultObjectSizeHeight ) );
2160 // subtracting the horizontal difference of the latest handle from shape position
2161 if ( !aInteractionHandles.empty() )
2163 sal_Int32 nHandlePos = aInteractionHandles[ aInteractionHandles.size() - 1 ].xInteraction->getPosition().X;
2164 aRect1.Move( aRect.Left() - nHandlePos, 0 );
2167 ImpJustifyRect( aRect1 );
2168 rStat.SetActionRect( aRect1 );
2169 aRect = aRect1;
2170 SetRectsDirty();
2172 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd( aInteractionHandles.end() );
2173 aIter != aEnd ; ++aIter)
2177 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_CREATE_FIXED )
2178 aIter->xInteraction->setControllerPosition( awt::Point( rStat.GetStart().X(), rStat.GetStart().Y() ) );
2180 catch ( const uno::RuntimeException& )
2185 SetBoundRectDirty();
2186 bSnapRectDirty=sal_True;
2189 bool SdrObjCustomShape::BegCreate( SdrDragStat& rDrag )
2191 return SdrTextObj::BegCreate( rDrag );
2194 bool SdrObjCustomShape::MovCreate(SdrDragStat& rStat)
2196 SdrView* pView = rStat.GetView(); // #i37448#
2197 if( pView && pView->IsSolidDragging() )
2199 InvalidateRenderGeometry();
2201 DragCreateObject( rStat );
2202 SetRectsDirty();
2203 return sal_True;
2206 bool SdrObjCustomShape::EndCreate( SdrDragStat& rStat, SdrCreateCmd eCmd )
2208 DragCreateObject( rStat );
2210 if ( bTextFrame )
2212 if ( IsAutoGrowHeight() )
2214 // MinTextHeight
2215 long nHgt=aRect.GetHeight()-1;
2216 if (nHgt==1) nHgt=0;
2217 NbcSetMinTextFrameHeight( nHgt );
2219 if ( IsAutoGrowWidth() )
2221 // MinTextWidth
2222 long nWdt=aRect.GetWidth()-1;
2223 if (nWdt==1) nWdt=0;
2224 NbcSetMinTextFrameWidth( nWdt );
2226 // re-calculate text frame
2227 NbcAdjustTextFrameWidthAndHeight();
2229 SetRectsDirty();
2230 return ( eCmd == SDRCREATE_FORCEEND || rStat.GetPointAnz() >= 2 );
2233 basegfx::B2DPolyPolygon SdrObjCustomShape::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
2235 return GetLineGeometry( this, sal_False );
2238 ////////////////////////////////////////////////////////////////////////////////////////////////////
2240 // in context with the SdrObjCustomShape the SdrTextAutoGrowHeightItem == true -> Resize Shape to fit text,
2241 // the SdrTextAutoGrowWidthItem == true -> Word wrap text in Shape
2242 bool SdrObjCustomShape::IsAutoGrowHeight() const
2244 const SfxItemSet& rSet = GetMergedItemSet();
2245 bool bIsAutoGrowHeight = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
2246 if ( bIsAutoGrowHeight && IsVerticalWriting() )
2247 bIsAutoGrowHeight = ((SdrTextWordWrapItem&)(rSet.Get(SDRATTR_TEXT_WORDWRAP))).GetValue() == sal_False;
2248 return bIsAutoGrowHeight;
2250 bool SdrObjCustomShape::IsAutoGrowWidth() const
2252 const SfxItemSet& rSet = GetMergedItemSet();
2253 bool bIsAutoGrowWidth = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
2254 if ( bIsAutoGrowWidth && !IsVerticalWriting() )
2255 bIsAutoGrowWidth = ((SdrTextWordWrapItem&)(rSet.Get(SDRATTR_TEXT_WORDWRAP))).GetValue() == sal_False;
2256 return bIsAutoGrowWidth;
2259 /* The following method is identical to the SdrTextObj::SetVerticalWriting method, the only difference
2260 is that the SdrAutoGrowWidthItem and SdrAutoGrowHeightItem are not exchanged if the vertical writing
2261 mode has been changed */
2263 void SdrObjCustomShape::SetVerticalWriting( sal_Bool bVertical )
2265 ForceOutlinerParaObject();
2267 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
2269 DBG_ASSERT( pOutlinerParaObject, "SdrTextObj::SetVerticalWriting() without OutlinerParaObject!" );
2271 if( pOutlinerParaObject )
2273 if(pOutlinerParaObject->IsVertical() != (bool)bVertical)
2275 // get item settings
2276 const SfxItemSet& rSet = GetObjectItemSet();
2278 // Also exchange horizontal and vertical adjust items
2279 SdrTextHorzAdjust eHorz = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue();
2280 SdrTextVertAdjust eVert = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
2282 // rescue object size
2283 Rectangle aObjectRect = GetSnapRect();
2285 // prepare ItemSet to set exchanged width and height items
2286 SfxItemSet aNewSet(*rSet.GetPool(),
2287 SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT,
2288 // Expanded item ranges to also support horizontal and vertical adjust.
2289 SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST,
2290 SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST,
2291 0, 0);
2293 aNewSet.Put(rSet);
2295 // Exchange horizontal and vertical adjusts
2296 switch(eVert)
2298 case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break;
2299 case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break;
2300 case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break;
2301 case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break;
2303 switch(eHorz)
2305 case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break;
2306 case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break;
2307 case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break;
2308 case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break;
2311 SetObjectItemSet( aNewSet );
2312 pOutlinerParaObject = GetOutlinerParaObject();
2313 if ( pOutlinerParaObject )
2314 pOutlinerParaObject->SetVertical(bVertical);
2316 // restore object size
2317 SetSnapRect(aObjectRect);
2321 bool SdrObjCustomShape::AdjustTextFrameWidthAndHeight(Rectangle& rR, bool bHgt, bool bWdt) const
2323 if ( pModel && HasText() && !rR.IsEmpty() )
2325 bool bWdtGrow=bWdt && IsAutoGrowWidth();
2326 bool bHgtGrow=bHgt && IsAutoGrowHeight();
2327 if ( bWdtGrow || bHgtGrow )
2329 Rectangle aR0(rR);
2330 long nHgt=0,nMinHgt=0,nMaxHgt=0;
2331 long nWdt=0,nMinWdt=0,nMaxWdt=0;
2332 Size aSiz(rR.GetSize()); aSiz.Width()--; aSiz.Height()--;
2333 Size aMaxSiz(100000,100000);
2334 Size aTmpSiz(pModel->GetMaxObjSize());
2335 if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width();
2336 if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height();
2337 if (bWdtGrow)
2339 nMinWdt=GetMinTextFrameWidth();
2340 nMaxWdt=GetMaxTextFrameWidth();
2341 if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width();
2342 if (nMinWdt<=0) nMinWdt=1;
2343 aSiz.Width()=nMaxWdt;
2345 if (bHgtGrow)
2347 nMinHgt=GetMinTextFrameHeight();
2348 nMaxHgt=GetMaxTextFrameHeight();
2349 if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height();
2350 if (nMinHgt<=0) nMinHgt=1;
2351 aSiz.Height()=nMaxHgt;
2353 long nHDist=GetTextLeftDistance()+GetTextRightDistance();
2354 long nVDist=GetTextUpperDistance()+GetTextLowerDistance();
2355 aSiz.Width()-=nHDist;
2356 aSiz.Height()-=nVDist;
2357 if ( aSiz.Width() < 2 )
2358 aSiz.Width() = 2; // minimum size=2
2359 if ( aSiz.Height() < 2 )
2360 aSiz.Height() = 2; // minimum size=2
2362 if(pEdtOutl)
2364 pEdtOutl->SetMaxAutoPaperSize( aSiz );
2365 if (bWdtGrow)
2367 Size aSiz2(pEdtOutl->CalcTextSize());
2368 nWdt=aSiz2.Width()+1; // a little more tolerance
2369 if (bHgtGrow) nHgt=aSiz2.Height()+1; // a little more tolerance
2370 } else
2372 nHgt=pEdtOutl->GetTextHeight()+1; // a little more tolerance
2375 else
2377 Outliner& rOutliner=ImpGetDrawOutliner();
2378 rOutliner.SetPaperSize(aSiz);
2379 rOutliner.SetUpdateMode(sal_True);
2380 // TODO: add the optimization with bPortionInfoChecked again.
2381 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
2382 if( pOutlinerParaObject != NULL )
2384 rOutliner.SetText(*pOutlinerParaObject);
2385 rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
2387 if ( bWdtGrow )
2389 Size aSiz2(rOutliner.CalcTextSize());
2390 nWdt=aSiz2.Width()+1; // a little more tolerance
2391 if ( bHgtGrow )
2392 nHgt=aSiz2.Height()+1; // a little more tolerance
2394 else
2395 nHgt = rOutliner.GetTextHeight()+1; // a little more tolerance
2396 rOutliner.Clear();
2398 if ( nWdt < nMinWdt )
2399 nWdt = nMinWdt;
2400 if ( nWdt > nMaxWdt )
2401 nWdt = nMaxWdt;
2402 nWdt += nHDist;
2403 if ( nWdt < 1 )
2404 nWdt = 1; // nHDist may also be negative
2405 if ( nHgt < nMinHgt )
2406 nHgt = nMinHgt;
2407 if ( nHgt > nMaxHgt )
2408 nHgt = nMaxHgt;
2409 nHgt+=nVDist;
2410 if ( nHgt < 1 )
2411 nHgt = 1; // nVDist may also be negative
2412 long nWdtGrow = nWdt-(rR.Right()-rR.Left());
2413 long nHgtGrow = nHgt-(rR.Bottom()-rR.Top());
2414 if ( nWdtGrow == 0 )
2415 bWdtGrow = sal_False;
2416 if ( nHgtGrow == 0 )
2417 bHgtGrow=sal_False;
2418 if ( bWdtGrow || bHgtGrow )
2420 if ( bWdtGrow )
2422 SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
2423 if ( eHAdj == SDRTEXTHORZADJUST_LEFT )
2424 rR.Right()+=nWdtGrow;
2425 else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT )
2426 rR.Left()-=nWdtGrow;
2427 else
2429 long nWdtGrow2=nWdtGrow/2;
2430 rR.Left()-=nWdtGrow2;
2431 rR.Right()=rR.Left()+nWdt;
2434 if ( bHgtGrow )
2436 SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
2437 if ( eVAdj == SDRTEXTVERTADJUST_TOP )
2438 rR.Bottom()+=nHgtGrow;
2439 else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM )
2440 rR.Top()-=nHgtGrow;
2441 else
2443 long nHgtGrow2=nHgtGrow/2;
2444 rR.Top()-=nHgtGrow2;
2445 rR.Bottom()=rR.Top()+nHgt;
2448 if ( aGeo.nDrehWink )
2450 Point aD1(rR.TopLeft());
2451 aD1-=aR0.TopLeft();
2452 Point aD2(aD1);
2453 RotatePoint(aD2,Point(),aGeo.nSin,aGeo.nCos);
2454 aD2-=aD1;
2455 rR.Move(aD2.X(),aD2.Y());
2457 return sal_True;
2461 return sal_False;
2464 Rectangle SdrObjCustomShape::ImpCalculateTextFrame( const bool bHgt, const bool bWdt )
2466 Rectangle aReturnValue;
2468 Rectangle aOldTextRect( aRect ); // <- initial text rectangle
2470 Rectangle aNewTextRect( aRect ); // <- new text rectangle returned from the custom shape renderer,
2471 GetTextBounds( aNewTextRect ); // it depends to the current logical shape size
2473 Rectangle aAdjustedTextRect( aNewTextRect ); // <- new text rectangle is being tested by AdjustTextFrameWidthAndHeight to ensure
2474 if ( AdjustTextFrameWidthAndHeight( aAdjustedTextRect, bHgt, bWdt ) ) // that the new text rectangle is matching the current text size from the outliner
2476 if ( ( aAdjustedTextRect != aNewTextRect ) && ( aOldTextRect != aAdjustedTextRect ) )
2478 aReturnValue = aRect;
2479 double fXScale = (double)aOldTextRect.GetWidth() / (double)aNewTextRect.GetWidth();
2480 double fYScale = (double)aOldTextRect.GetHeight() / (double)aNewTextRect.GetHeight();
2481 double fRightDiff = (double)( aAdjustedTextRect.Right() - aNewTextRect.Right() ) * fXScale;
2482 double fLeftDiff = (double)( aAdjustedTextRect.Left() - aNewTextRect.Left() ) * fXScale;
2483 double fTopDiff = (double)( aAdjustedTextRect.Top() - aNewTextRect.Top() ) * fYScale;
2484 double fBottomDiff= (double)( aAdjustedTextRect.Bottom()- aNewTextRect.Bottom()) * fYScale;
2485 aReturnValue.Left() += (sal_Int32)fLeftDiff;
2486 aReturnValue.Right() += (sal_Int32)fRightDiff;
2487 aReturnValue.Top() += (sal_Int32)fTopDiff;
2488 aReturnValue.Bottom() += (sal_Int32)fBottomDiff;
2491 return aReturnValue;
2494 bool SdrObjCustomShape::NbcAdjustTextFrameWidthAndHeight(bool bHgt, bool bWdt)
2496 Rectangle aNewTextRect = ImpCalculateTextFrame( bHgt, bWdt );
2497 bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != aRect );
2498 if ( bRet )
2500 // taking care of handles that should not been changed
2501 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
2503 aRect = aNewTextRect;
2504 SetRectsDirty();
2505 SetChanged();
2507 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd ( aInteractionHandles.end() );
2508 aIter != aEnd ; ++aIter)
2512 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2513 aIter->xInteraction->setControllerPosition( aIter->aPosition );
2515 catch ( const uno::RuntimeException& )
2519 InvalidateRenderGeometry();
2521 return bRet;
2523 bool SdrObjCustomShape::AdjustTextFrameWidthAndHeight(bool bHgt, bool bWdt)
2525 Rectangle aNewTextRect = ImpCalculateTextFrame( bHgt, bWdt );
2526 bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != aRect );
2527 if ( bRet )
2529 Rectangle aBoundRect0;
2530 if ( pUserCall )
2531 aBoundRect0 = GetCurrentBoundRect();
2533 // taking care of handles that should not been changed
2534 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
2536 aRect = aNewTextRect;
2537 SetRectsDirty();
2539 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd( aInteractionHandles.end() ) ;
2540 aIter != aEnd ; ++aIter)
2544 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2545 aIter->xInteraction->setControllerPosition( aIter->aPosition );
2547 catch ( const uno::RuntimeException& )
2552 InvalidateRenderGeometry();
2553 SetChanged();
2554 BroadcastObjectChange();
2555 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
2557 return bRet;
2559 sal_Bool SdrObjCustomShape::BegTextEdit( SdrOutliner& rOutl )
2561 return SdrTextObj::BegTextEdit( rOutl );
2563 void SdrObjCustomShape::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const
2565 Size aPaperMin,aPaperMax;
2566 Rectangle aViewInit;
2567 TakeTextAnchorRect( aViewInit );
2568 if ( aGeo.nDrehWink )
2570 Point aCenter(aViewInit.Center());
2571 aCenter-=aViewInit.TopLeft();
2572 Point aCenter0(aCenter);
2573 RotatePoint(aCenter,Point(),aGeo.nSin,aGeo.nCos);
2574 aCenter-=aCenter0;
2575 aViewInit.Move(aCenter.X(),aCenter.Y());
2577 Size aAnkSiz(aViewInit.GetSize());
2578 aAnkSiz.Width()--; aAnkSiz.Height()--; // because GetSize() adds 1
2579 Size aMaxSiz(1000000,1000000);
2580 if (pModel!=NULL) {
2581 Size aTmpSiz(pModel->GetMaxObjSize());
2582 if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width();
2583 if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height();
2585 SdrTextHorzAdjust eHAdj(GetTextHorizontalAdjust());
2586 SdrTextVertAdjust eVAdj(GetTextVerticalAdjust());
2588 long nMinWdt = GetMinTextFrameWidth();
2589 long nMinHgt = GetMinTextFrameHeight();
2590 long nMaxWdt = GetMaxTextFrameWidth();
2591 long nMaxHgt = GetMaxTextFrameHeight();
2592 if (nMinWdt<1) nMinWdt=1;
2593 if (nMinHgt<1) nMinHgt=1;
2594 if ( nMaxWdt == 0 || nMaxWdt > aMaxSiz.Width() )
2595 nMaxWdt = aMaxSiz.Width();
2596 if ( nMaxHgt == 0 || nMaxHgt > aMaxSiz.Height() )
2597 nMaxHgt=aMaxSiz.Height();
2599 if (((SdrTextWordWrapItem&)(GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue())
2601 if ( IsVerticalWriting() )
2603 nMaxHgt = aAnkSiz.Height();
2604 nMinHgt = nMaxHgt;
2606 else
2608 nMaxWdt = aAnkSiz.Width();
2609 nMinWdt = nMaxWdt;
2612 aPaperMax.Width()=nMaxWdt;
2613 aPaperMax.Height()=nMaxHgt;
2615 aPaperMin.Width()=nMinWdt;
2616 aPaperMin.Height()=nMinHgt;
2618 if ( pViewMin )
2620 *pViewMin = aViewInit;
2622 long nXFree = aAnkSiz.Width() - aPaperMin.Width();
2623 if ( eHAdj == SDRTEXTHORZADJUST_LEFT )
2624 pViewMin->Right() -= nXFree;
2625 else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT )
2626 pViewMin->Left() += nXFree;
2627 else { pViewMin->Left() += nXFree / 2; pViewMin->Right() = pViewMin->Left() + aPaperMin.Width(); }
2629 long nYFree = aAnkSiz.Height() - aPaperMin.Height();
2630 if ( eVAdj == SDRTEXTVERTADJUST_TOP )
2631 pViewMin->Bottom() -= nYFree;
2632 else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM )
2633 pViewMin->Top() += nYFree;
2634 else { pViewMin->Top() += nYFree / 2; pViewMin->Bottom() = pViewMin->Top() + aPaperMin.Height(); }
2637 if( IsVerticalWriting() )
2638 aPaperMin.Width() = 0;
2639 else
2640 aPaperMin.Height() = 0;
2642 if( eHAdj != SDRTEXTHORZADJUST_BLOCK )
2643 aPaperMin.Width()=0;
2645 // For complete vertical adjust support, set paper min height to 0, here.
2646 if(SDRTEXTVERTADJUST_BLOCK != eVAdj )
2647 aPaperMin.Height() = 0;
2649 if (pPaperMin!=NULL) *pPaperMin=aPaperMin;
2650 if (pPaperMax!=NULL) *pPaperMax=aPaperMax;
2651 if (pViewInit!=NULL) *pViewInit=aViewInit;
2653 void SdrObjCustomShape::EndTextEdit( SdrOutliner& rOutl )
2655 SdrTextObj::EndTextEdit( rOutl );
2656 InvalidateRenderGeometry();
2658 void SdrObjCustomShape::TakeTextAnchorRect( Rectangle& rAnchorRect ) const
2660 if ( GetTextBounds( rAnchorRect ) )
2662 Point aRotateRef( maSnapRect.Center() );
2663 rAnchorRect.Left() += GetTextLeftDistance();
2664 rAnchorRect.Top() += GetTextUpperDistance();
2665 rAnchorRect.Right() -= GetTextRightDistance();
2666 rAnchorRect.Bottom() -= GetTextLowerDistance();
2667 ImpJustifyRect( rAnchorRect );
2669 if ( rAnchorRect.GetWidth() < 2 )
2670 rAnchorRect.Right() = rAnchorRect.Left() + 1; // minimal width is 2
2671 if ( rAnchorRect.GetHeight() < 2 )
2672 rAnchorRect.Bottom() = rAnchorRect.Top() + 1; // minimal height is 2
2673 if ( aGeo.nDrehWink )
2675 Point aP( rAnchorRect.TopLeft() );
2676 RotatePoint( aP, aRotateRef, aGeo.nSin, aGeo. nCos );
2677 rAnchorRect.SetPos( aP );
2680 else
2681 SdrTextObj::TakeTextAnchorRect( rAnchorRect );
2683 void SdrObjCustomShape::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, bool bNoEditText,
2684 Rectangle* pAnchorRect, bool /*bLineWidth*/) const
2686 Rectangle aAnkRect; // Rect in which we anchor
2687 TakeTextAnchorRect(aAnkRect);
2688 SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
2689 SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
2690 sal_uIntPtr nStat0=rOutliner.GetControlWord();
2691 Size aNullSize;
2693 rOutliner.SetControlWord(nStat0|EE_CNTRL_AUTOPAGESIZE);
2694 rOutliner.SetMinAutoPaperSize(aNullSize);
2695 sal_Int32 nMaxAutoPaperWidth = 1000000;
2696 sal_Int32 nMaxAutoPaperHeight= 1000000;
2698 long nAnkWdt=aAnkRect.GetWidth();
2699 long nAnkHgt=aAnkRect.GetHeight();
2701 if (((SdrTextWordWrapItem&)(GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue())
2703 if ( IsVerticalWriting() )
2704 nMaxAutoPaperHeight = nAnkHgt;
2705 else
2706 nMaxAutoPaperWidth = nAnkWdt;
2708 if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting())
2710 rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0));
2713 if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting())
2715 rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt));
2717 rOutliner.SetMaxAutoPaperSize( Size( nMaxAutoPaperWidth, nMaxAutoPaperHeight ) );
2718 rOutliner.SetPaperSize( aNullSize );
2720 // put text into the Outliner - if necessary the use the text from the EditOutliner
2721 OutlinerParaObject* pPara= GetOutlinerParaObject();
2722 if (pEdtOutl && !bNoEditText)
2723 pPara=pEdtOutl->CreateParaObject();
2725 if (pPara)
2727 bool bHitTest = false;
2728 if( pModel )
2729 bHitTest = &pModel->GetHitTestOutliner() == &rOutliner;
2731 const SdrTextObj* pTestObj = rOutliner.GetTextObj();
2732 if( !pTestObj || !bHitTest || pTestObj != this ||
2733 pTestObj->GetOutlinerParaObject() != GetOutlinerParaObject() )
2735 if( bHitTest )
2736 rOutliner.SetTextObj( this );
2738 rOutliner.SetUpdateMode(sal_True);
2739 rOutliner.SetText(*pPara);
2742 else
2744 rOutliner.SetTextObj( NULL );
2746 if (pEdtOutl && !bNoEditText && pPara)
2747 delete pPara;
2749 rOutliner.SetUpdateMode(sal_True);
2750 rOutliner.SetControlWord(nStat0);
2752 SdrText* pText = getActiveText();
2753 if( pText )
2754 pText->CheckPortionInfo( rOutliner );
2756 Point aTextPos(aAnkRect.TopLeft());
2757 Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() has a little added tolerance, no?
2759 // For draw objects containing text correct horizontal/vertical alignment if text is bigger
2760 // than the object itself. Without that correction, the text would always be
2761 // formatted to the left edge (or top edge when vertical) of the draw object.
2763 if( !IsTextFrame() )
2765 if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting())
2767 // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK,
2768 // else the alignment is wanted.
2769 if(SDRTEXTHORZADJUST_BLOCK == eHAdj)
2771 eHAdj = SDRTEXTHORZADJUST_CENTER;
2775 if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting())
2777 // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK,
2778 // else the alignment is wanted.
2779 if(SDRTEXTVERTADJUST_BLOCK == eVAdj)
2781 eVAdj = SDRTEXTVERTADJUST_CENTER;
2786 if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT)
2788 long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width();
2789 if (eHAdj==SDRTEXTHORZADJUST_CENTER)
2790 aTextPos.X()+=nFreeWdt/2;
2791 if (eHAdj==SDRTEXTHORZADJUST_RIGHT)
2792 aTextPos.X()+=nFreeWdt;
2794 if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM)
2796 long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height();
2797 if (eVAdj==SDRTEXTVERTADJUST_CENTER)
2798 aTextPos.Y()+=nFreeHgt/2;
2799 if (eVAdj==SDRTEXTVERTADJUST_BOTTOM)
2800 aTextPos.Y()+=nFreeHgt;
2802 if (aGeo.nDrehWink!=0)
2803 RotatePoint(aTextPos,aAnkRect.TopLeft(),aGeo.nSin,aGeo.nCos);
2805 if (pAnchorRect)
2806 *pAnchorRect=aAnkRect;
2808 // using rTextRect together with ContourFrame doesn't always work correctly
2809 rTextRect=Rectangle(aTextPos,aTextSiz);
2812 void SdrObjCustomShape::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject)
2814 SdrTextObj::NbcSetOutlinerParaObject( pTextObject );
2815 SetBoundRectDirty();
2816 SetRectsDirty(sal_True);
2817 InvalidateRenderGeometry();
2820 SdrObjCustomShape* SdrObjCustomShape::Clone() const
2822 return CloneHelper< SdrObjCustomShape >();
2825 SdrObjCustomShape& SdrObjCustomShape::operator=(const SdrObjCustomShape& rObj)
2827 if( this == &rObj )
2828 return *this;
2829 SdrTextObj::operator=( rObj );
2830 aName = rObj.aName;
2831 fObjectRotation = rObj.fObjectRotation;
2832 InvalidateRenderGeometry();
2833 return *this;
2837 void SdrObjCustomShape::TakeObjNameSingul(XubString& rName) const
2839 rName = ImpGetResStr(STR_ObjNameSingulCUSTOMSHAPE);
2840 String aNm( GetName() );
2841 if( aNm.Len() )
2843 rName += sal_Unicode(' ');
2844 rName += sal_Unicode('\'');
2845 rName += aNm;
2846 rName += sal_Unicode('\'');
2850 void SdrObjCustomShape::TakeObjNamePlural(XubString& rName) const
2852 rName=ImpGetResStr(STR_ObjNamePluralCUSTOMSHAPE);
2855 basegfx::B2DPolyPolygon SdrObjCustomShape::TakeXorPoly() const
2857 return GetLineGeometry( (SdrObjCustomShape*)this, sal_False );
2860 basegfx::B2DPolyPolygon SdrObjCustomShape::TakeContour() const
2862 const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
2863 if ( pSdrObject )
2864 return pSdrObject->TakeContour();
2865 return basegfx::B2DPolyPolygon();
2868 SdrObject* SdrObjCustomShape::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const
2870 // #i37011#
2871 SdrObject* pRetval = 0L;
2872 SdrObject* pRenderedCustomShape = 0L;
2874 if ( !mXRenderedCustomShape.is() )
2876 // force CustomShape
2877 ((SdrObjCustomShape*)this)->GetSdrObjectFromCustomShape();
2880 if ( mXRenderedCustomShape.is() )
2882 pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape );
2885 if ( pRenderedCustomShape )
2887 SdrObject* pCandidate = pRenderedCustomShape->Clone();
2888 DBG_ASSERT(pCandidate, "SdrObjCustomShape::DoConvertToPolyObj: Could not clone SdrObject (!)");
2889 pCandidate->SetModel(GetModel());
2890 pRetval = pCandidate->DoConvertToPolyObj(bBezier, bAddText);
2891 SdrObject::Free( pCandidate );
2893 if(pRetval)
2895 const sal_Bool bShadow(((SdrShadowItem&)GetMergedItem(SDRATTR_SHADOW)).GetValue());
2896 if(bShadow)
2898 pRetval->SetMergedItem(SdrShadowItem(sal_True));
2902 if(bAddText && HasText() && !IsTextPath())
2904 pRetval = ImpConvertAddText(pRetval, bBezier);
2908 return pRetval;
2911 void SdrObjCustomShape::NbcSetStyleSheet( SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr )
2913 // #i40944#
2914 InvalidateRenderGeometry();
2915 SdrObject::NbcSetStyleSheet( pNewStyleSheet, bDontRemoveHardAttr );
2918 void SdrObjCustomShape::SetPage( SdrPage* pNewPage )
2920 SdrTextObj::SetPage( pNewPage );
2922 if( pNewPage )
2924 // invalidating rectangles by SetRectsDirty is not sufficient,
2925 // AdjustTextFrameWidthAndHeight() also has to be made, both
2926 // actions are done by NbcSetSnapRect
2927 Rectangle aTmp( aRect ); //creating temporary rectangle #i61108#
2928 NbcSetSnapRect( aTmp );
2932 SdrObjGeoData* SdrObjCustomShape::NewGeoData() const
2934 return new SdrAShapeObjGeoData;
2937 void SdrObjCustomShape::SaveGeoData(SdrObjGeoData& rGeo) const
2939 SdrTextObj::SaveGeoData( rGeo );
2940 SdrAShapeObjGeoData& rAGeo=(SdrAShapeObjGeoData&)rGeo;
2941 rAGeo.fObjectRotation = fObjectRotation;
2942 rAGeo.bMirroredX = IsMirroredX();
2943 rAGeo.bMirroredY = IsMirroredY();
2945 const OUString sAdjustmentValues( "AdjustmentValues" );
2946 Any* pAny( ( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ).GetPropertyValueByName( sAdjustmentValues ) );
2947 if ( pAny )
2948 *pAny >>= rAGeo.aAdjustmentSeq;
2951 void SdrObjCustomShape::RestGeoData(const SdrObjGeoData& rGeo)
2953 SdrTextObj::RestGeoData( rGeo );
2954 SdrAShapeObjGeoData& rAGeo=(SdrAShapeObjGeoData&)rGeo;
2955 fObjectRotation = rAGeo.fObjectRotation;
2956 SetMirroredX( rAGeo.bMirroredX );
2957 SetMirroredY( rAGeo.bMirroredY );
2959 SdrCustomShapeGeometryItem rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
2960 const OUString sAdjustmentValues( "AdjustmentValues" );
2961 PropertyValue aPropVal;
2962 aPropVal.Name = sAdjustmentValues;
2963 aPropVal.Value <<= rAGeo.aAdjustmentSeq;
2964 rGeometryItem.SetPropertyValue( aPropVal );
2965 SetMergedItem( rGeometryItem );
2967 InvalidateRenderGeometry();
2970 void SdrObjCustomShape::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
2972 // break up matrix
2973 basegfx::B2DTuple aScale;
2974 basegfx::B2DTuple aTranslate;
2975 double fRotate, fShearX;
2976 rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
2978 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
2979 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
2980 if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
2982 aScale.setX(fabs(aScale.getX()));
2983 aScale.setY(fabs(aScale.getY()));
2984 fRotate = fmod(fRotate + F_PI, F_2PI);
2987 // reset object shear and rotations
2988 aGeo.nDrehWink = 0;
2989 aGeo.RecalcSinCos();
2990 aGeo.nShearWink = 0;
2991 aGeo.RecalcTan();
2993 // force metric to pool metric
2994 const SfxMapUnit eMapUnit(GetObjectMapUnit());
2995 if(eMapUnit != SFX_MAPUNIT_100TH_MM)
2997 switch(eMapUnit)
2999 case SFX_MAPUNIT_TWIP :
3001 // position
3002 aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
3003 aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
3005 // size
3006 aScale.setX(ImplMMToTwips(aScale.getX()));
3007 aScale.setY(ImplMMToTwips(aScale.getY()));
3009 break;
3011 default:
3013 OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
3018 // if anchor is used, make position relative to it
3019 if( pModel && pModel->IsWriter() )
3021 if(GetAnchorPos().X() || GetAnchorPos().Y())
3023 aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3027 // build and set BaseRect (use scale)
3028 Point aPoint = Point();
3029 Size aSize(FRound(aScale.getX()), FRound(aScale.getY()));
3030 // fdo#47434 We need a valid rectangle here
3031 if( !aSize.Height() ) aSize.setHeight( 1 );
3032 if( !aSize.Width() ) aSize.setWidth( 1 );
3034 Rectangle aBaseRect(aPoint, aSize);
3035 SetSnapRect(aBaseRect);
3037 // shear?
3038 if(!basegfx::fTools::equalZero(fShearX))
3040 GeoStat aGeoStat;
3041 aGeoStat.nShearWink = FRound((atan(fShearX) / F_PI180) * 100.0);
3042 aGeoStat.RecalcTan();
3043 Shear(Point(), aGeoStat.nShearWink, aGeoStat.nTan, sal_False);
3046 // rotation?
3047 if(!basegfx::fTools::equalZero(fRotate))
3049 GeoStat aGeoStat;
3051 // #i78696#
3052 // fRotate is mathematically correct, but aGeoStat.nDrehWink is
3053 // mirrored -> mirror value here
3054 aGeoStat.nDrehWink = NormAngle360(FRound(-fRotate / F_PI18000));
3055 aGeoStat.RecalcSinCos();
3056 Rotate(Point(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos);
3059 // translate?
3060 if(!aTranslate.equalZero())
3062 Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY())));
3066 // taking fObjectRotation instead of aGeo.nWink
3067 sal_Bool SdrObjCustomShape::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
3069 // get turn and shear
3070 double fRotate = fObjectRotation * F_PI180;
3071 double fShearX = (aGeo.nShearWink / 100.0) * F_PI180;
3073 // get aRect, this is the unrotated snaprect
3074 Rectangle aRectangle(aRect);
3076 sal_Bool bMirroredX = IsMirroredX();
3077 sal_Bool bMirroredY = IsMirroredY();
3078 if ( bMirroredX || bMirroredY )
3079 { // we have to retrieve the unmirrored rect
3081 GeoStat aNewGeo( aGeo );
3083 if ( bMirroredX )
3085 Polygon aPol( Rect2Poly( aRect, aNewGeo ) );
3086 Rectangle aBoundRect( aPol.GetBoundRect() );
3088 Point aRef1( ( aBoundRect.Left() + aBoundRect.Right() ) >> 1, aBoundRect.Top() );
3089 Point aRef2( aRef1.X(), aRef1.Y() + 1000 );
3090 sal_uInt16 i;
3091 sal_uInt16 nPntAnz=aPol.GetSize();
3092 for (i=0; i<nPntAnz; i++)
3094 MirrorPoint(aPol[i],aRef1,aRef2);
3096 // mirror polygon and move it a bit
3097 Polygon aPol0(aPol);
3098 aPol[0]=aPol0[1];
3099 aPol[1]=aPol0[0];
3100 aPol[2]=aPol0[3];
3101 aPol[3]=aPol0[2];
3102 aPol[4]=aPol0[1];
3103 Poly2Rect(aPol,aRectangle,aNewGeo);
3105 if ( bMirroredY )
3107 Polygon aPol( Rect2Poly( aRectangle, aNewGeo ) );
3108 Rectangle aBoundRect( aPol.GetBoundRect() );
3110 Point aRef1( aBoundRect.Left(), ( aBoundRect.Top() + aBoundRect.Bottom() ) >> 1 );
3111 Point aRef2( aRef1.X() + 1000, aRef1.Y() );
3112 sal_uInt16 i;
3113 sal_uInt16 nPntAnz=aPol.GetSize();
3114 for (i=0; i<nPntAnz; i++)
3116 MirrorPoint(aPol[i],aRef1,aRef2);
3118 // mirror polygon and move it a bit
3119 Polygon aPol0(aPol);
3120 aPol[0]=aPol0[1];
3121 aPol[1]=aPol0[0];
3122 aPol[2]=aPol0[3];
3123 aPol[3]=aPol0[2];
3124 aPol[4]=aPol0[1];
3125 Poly2Rect(aPol,aRectangle,aNewGeo);
3129 // fill other values
3130 basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight());
3131 basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top());
3133 // position may be relative to anchorpos, convert
3134 if( pModel && pModel->IsWriter() )
3136 if(GetAnchorPos().X() || GetAnchorPos().Y())
3138 aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3142 // force MapUnit to 100th mm
3143 const SfxMapUnit eMapUnit(GetObjectMapUnit());
3144 if(eMapUnit != SFX_MAPUNIT_100TH_MM)
3146 switch(eMapUnit)
3148 case SFX_MAPUNIT_TWIP :
3150 // position
3151 aTranslate.setX(ImplTwipsToMM(aTranslate.getX()));
3152 aTranslate.setY(ImplTwipsToMM(aTranslate.getY()));
3154 // size
3155 aScale.setX(ImplTwipsToMM(aScale.getX()));
3156 aScale.setY(ImplTwipsToMM(aScale.getY()));
3158 break;
3160 default:
3162 OSL_FAIL("TRGetBaseGeometry: Missing unit translation to 100th mm!");
3167 // build matrix
3168 rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
3169 aScale,
3170 basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX),
3171 basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate,
3172 aTranslate);
3174 return sal_False;
3177 sdr::contact::ViewContact* SdrObjCustomShape::CreateObjectSpecificViewContact()
3179 return new sdr::contact::ViewContactOfSdrObjCustomShape(*this);
3182 // #i33136#
3183 bool SdrObjCustomShape::doConstructOrthogonal(const OUString& rName)
3185 bool bRetval(false);
3186 static OUString Imps_sNameASOrtho_quadrat( "quadrat" );
3187 static OUString Imps_sNameASOrtho_round_quadrat( "round-quadrat" );
3188 static OUString Imps_sNameASOrtho_circle( "circle" );
3189 static OUString Imps_sNameASOrtho_circle_pie( "circle-pie" );
3190 static OUString Imps_sNameASOrtho_ring( "ring" );
3192 if(Imps_sNameASOrtho_quadrat.equalsIgnoreAsciiCase(rName))
3194 bRetval = true;
3196 else if(Imps_sNameASOrtho_round_quadrat.equalsIgnoreAsciiCase(rName))
3198 bRetval = true;
3200 else if(Imps_sNameASOrtho_circle.equalsIgnoreAsciiCase(rName))
3202 bRetval = true;
3204 else if(Imps_sNameASOrtho_circle_pie.equalsIgnoreAsciiCase(rName))
3206 bRetval = true;
3208 else if(Imps_sNameASOrtho_ring.equalsIgnoreAsciiCase(rName))
3210 bRetval = true;
3213 return bRetval;
3216 // #i37011# centralize throw-away of render geometry
3217 void SdrObjCustomShape::InvalidateRenderGeometry()
3219 mXRenderedCustomShape = 0L;
3220 SdrObject::Free( mpLastShadowGeometry );
3221 mpLastShadowGeometry = 0L;
3224 void SdrObjCustomShape::impl_setUnoShape(const uno::Reference<uno::XInterface>& rxUnoShape)
3226 SdrTextObj::impl_setUnoShape(rxUnoShape);
3228 // The shape engine is created with _current_ shape. This means we
3229 // _must_ reset it when the shape changes.
3230 mxCustomShapeEngine.set(0);
3233 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */