xref: /aoo41x/main/svx/source/svdraw/svdoashp.cxx (revision a5258243)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 #include <svx/svdoashp.hxx>
31 #include "svx/unoapi.hxx"
32 #include <svx/unoshape.hxx>
33 #include <ucbhelper/content.hxx>
34 #include <ucbhelper/contentbroker.hxx>
35 #include <unotools/datetime.hxx>
36 #include <sfx2/lnkbase.hxx>
37 #include <tools/urlobj.hxx>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/drawing/XShape.hpp>
40 #include <com/sun/star/drawing/XCustomShapeEngine.hpp>
41 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
42 #include <com/sun/star/beans/PropertyValue.hpp>
43 #include <com/sun/star/awt/Rectangle.hpp>
44 #include "unopolyhelper.hxx"
45 #include <comphelper/processfactory.hxx>
46 #include <svl/urihelper.hxx>
47 #include <com/sun/star/uno/Sequence.h>
48 #include <svx/svdogrp.hxx>
49 #include <vcl/salbtype.hxx>		// FRound
50 #include <svx/svddrag.hxx>
51 #include <svx/xpool.hxx>
52 #include <svx/xpoly.hxx>
53 #include <svx/svdmodel.hxx>
54 #include <svx/svdpage.hxx>
55 #include "svx/svditer.hxx"
56 #include <svx/svdobj.hxx>
57 #include <svx/svdtrans.hxx>
58 #include <svx/svdetc.hxx>
59 #include <svx/svdattrx.hxx>  // NotPersistItems
60 #include <svx/svdoedge.hxx>  // #32383# Die Verbinder nach Move nochmal anbroadcasten
61 #include "svx/svdglob.hxx"   // StringCache
62 #include "svx/svdstr.hrc"    // Objektname
63 #include <editeng/eeitem.hxx>
64 #include "editeng/editstat.hxx"
65 #include <svx/svdoutl.hxx>
66 #include <editeng/outlobj.hxx>
67 #include <svx/sdtfchim.hxx>
68 #include "../svx/EnhancedCustomShapeGeometry.hxx"
69 #include "../svx/EnhancedCustomShapeTypeNames.hxx"
70 #include "../svx/EnhancedCustomShape2d.hxx"
71 #include <com/sun/star/beans/PropertyValues.hpp>
72 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
73 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
74 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
75 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
76 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
77 #include <editeng/writingmodeitem.hxx>
78 #include <svx/xlnclit.hxx>
79 #include <svx/svxids.hrc>
80 #include <svl/whiter.hxx>
81 #include <svx/sdr/properties/customshapeproperties.hxx>
82 #include <svx/sdr/contact/viewcontactofsdrobjcustomshape.hxx>
83 #include <svx/xlnclit.hxx>
84 #include <svx/xlntrit.hxx>
85 #include <svx/xfltrit.hxx>
86 #include <svx/xflclit.hxx>
87 #include <svx/xflgrit.hxx>
88 #include <svx/xflhtit.hxx>
89 #include <svx/xbtmpit.hxx>
90 #include <vcl/bmpacc.hxx>
91 #include <svx/svdview.hxx>
92 #include <basegfx/polygon/b2dpolypolygontools.hxx>
93 #include <basegfx/matrix/b2dhommatrix.hxx>
94 #include <basegfx/matrix/b2dhommatrixtools.hxx>
95 
96 // #104018# replace macros above with type-safe methods
97 inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); }
98 inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); }
99 
100 using namespace ::com::sun::star;
101 using namespace ::com::sun::star::uno;
102 using namespace ::com::sun::star::lang;
103 using namespace ::com::sun::star::beans;
104 using namespace ::com::sun::star::drawing;
105 
106 static MSO_SPT ImpGetCustomShapeType( const SdrObjCustomShape& rCustoShape )
107 {
108 	MSO_SPT eRetValue = mso_sptNil;
109 
110 	rtl::OUString aEngine( ( (SdrCustomShapeEngineItem&)rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ) ).GetValue() );
111 	if ( !aEngine.getLength() || aEngine.equalsAscii( "com.sun.star.drawing.EnhancedCustomShapeEngine" ) )
112 	{
113 		rtl::OUString sShapeType;
114 		const rtl::OUString	sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
115 		SdrCustomShapeGeometryItem& rGeometryItem( (SdrCustomShapeGeometryItem&)rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
116 		Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
117 		if ( pAny && ( *pAny >>= sShapeType ) )
118 			eRetValue = EnhancedCustomShapeTypeNames::Get( sShapeType );
119 	}
120 	return eRetValue;
121 };
122 
123 static sal_Bool ImpVerticalSwitch( const SdrObjCustomShape& rCustoShape )
124 {
125 	sal_Bool bRet = sal_False;
126 	MSO_SPT eShapeType( ImpGetCustomShapeType( rCustoShape ) );
127 	switch( eShapeType )
128 	{
129 		case mso_sptAccentBorderCallout90 :		// 2 ortho
130 		case mso_sptBorderCallout1 :			// 2 diag
131 		case mso_sptBorderCallout2 :			// 3
132 		{
133 			bRet = sal_True;
134 		}
135 		break;
136 /*
137 		case mso_sptCallout1 :
138 		case mso_sptAccentCallout1 :
139 		case mso_sptAccentBorderCallout1 :
140 		case mso_sptBorderCallout90 :
141 		case mso_sptCallout90 :
142 		case mso_sptAccentCallout90 :
143 		case mso_sptCallout2 :
144 		case mso_sptCallout3 :
145 		case mso_sptAccentCallout2 :
146 		case mso_sptAccentCallout3 :
147 		case mso_sptBorderCallout3 :
148 		case mso_sptAccentBorderCallout2 :
149 		case mso_sptAccentBorderCallout3 :
150 */
151 		default: break;
152 	}
153 	return bRet;
154 }
155 
156 ////////////////////////////////////////////////////////////////////////////////////////////////////
157 // #i37011# create a clone with all attributes changed to shadow attributes
158 // and translation executed, too.
159 SdrObject* ImpCreateShadowObjectClone(const SdrObject& rOriginal, const SfxItemSet& rOriginalSet)
160 {
161 	SdrObject* pRetval = 0L;
162 	const sal_Bool bShadow(((SdrShadowItem&)rOriginalSet.Get(SDRATTR_SHADOW)).GetValue());
163 
164 	if(bShadow)
165 	{
166 		// create a shadow representing object
167 		const sal_Int32 nXDist(((SdrShadowXDistItem&)(rOriginalSet.Get(SDRATTR_SHADOWXDIST))).GetValue());
168 		const sal_Int32 nYDist(((SdrShadowYDistItem&)(rOriginalSet.Get(SDRATTR_SHADOWYDIST))).GetValue());
169 		const ::Color aShadowColor(((SdrShadowColorItem&)(rOriginalSet.Get(SDRATTR_SHADOWCOLOR))).GetColorValue());
170 		const sal_uInt16 nShadowTransparence(((SdrShadowTransparenceItem&)(rOriginalSet.Get(SDRATTR_SHADOWTRANSPARENCE))).GetValue());
171 		pRetval = rOriginal.Clone();
172 		DBG_ASSERT(pRetval, "ImpCreateShadowObjectClone: Could not clone object (!)");
173 
174 		// look for used stuff
175 		SdrObjListIter aIterator(rOriginal);
176 		sal_Bool bLineUsed(sal_False);
177 		sal_Bool bAllFillUsed(sal_False);
178 		sal_Bool bSolidFillUsed(sal_False);
179 		sal_Bool bGradientFillUsed(sal_False);
180 		sal_Bool bHatchFillUsed(sal_False);
181 		sal_Bool bBitmapFillUsed(sal_False);
182 
183 		while(aIterator.IsMore())
184 		{
185 			SdrObject* pObj = aIterator.Next();
186 			XFillStyle eFillStyle = ((XFillStyleItem&)(pObj->GetMergedItem(XATTR_FILLSTYLE))).GetValue();
187 
188 			if(!bLineUsed)
189 			{
190 				XLineStyle eLineStyle = ((XLineStyleItem&)(pObj->GetMergedItem(XATTR_LINESTYLE))).GetValue();
191 
192 				if(XLINE_NONE != eLineStyle)
193 				{
194 					bLineUsed = sal_True;
195 				}
196 			}
197 
198 			if(!bAllFillUsed)
199 			{
200 				if(!bSolidFillUsed && XFILL_SOLID == eFillStyle)
201 				{
202 					bSolidFillUsed = sal_True;
203 					bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed);
204 				}
205 				if(!bGradientFillUsed && XFILL_GRADIENT == eFillStyle)
206 				{
207 					bGradientFillUsed = sal_True;
208 					bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed);
209 				}
210 				if(!bHatchFillUsed && XFILL_HATCH == eFillStyle)
211 				{
212 					bHatchFillUsed = sal_True;
213 					bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed);
214 				}
215 				if(!bBitmapFillUsed && XFILL_BITMAP == eFillStyle)
216 				{
217 					bBitmapFillUsed = sal_True;
218 					bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed);
219 				}
220 			}
221 		}
222 
223 		// translate to shadow coordinates
224 		pRetval->NbcMove(Size(nXDist, nYDist));
225 
226 		// set items as needed
227 		SfxItemSet aTempSet(rOriginalSet);
228 
229 		// SJ: #40108# :-(  if a SvxWritingModeItem (Top->Bottom) is set the text object
230 		// is creating a paraobject, but paraobjects can not be created without model. So
231 		// we are preventing the crash by setting the writing mode always left to right,
232 		// this is not bad since our shadow geometry does not contain text.
233         aTempSet.Put( SvxWritingModeItem( com::sun::star::text::WritingMode_LR_TB, SDRATTR_TEXTDIRECTION ) );
234 
235 		// no shadow
236 		aTempSet.Put(SdrShadowItem(sal_False));
237 		aTempSet.Put(SdrShadowXDistItem(0L));
238 		aTempSet.Put(SdrShadowYDistItem(0L));
239 
240 		// line color and transparence like shadow
241 		if(bLineUsed)
242 		{
243 			aTempSet.Put(XLineColorItem(String(), aShadowColor));
244 			aTempSet.Put(XLineTransparenceItem(nShadowTransparence));
245 		}
246 
247 		// fill color and transparence like shadow
248 		if(bSolidFillUsed)
249 		{
250 			aTempSet.Put(XFillColorItem(String(), aShadowColor));
251 			aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
252 		}
253 
254 		// gradient and transparence like shadow
255 		if(bGradientFillUsed)
256 		{
257 			XGradient aGradient(((XFillGradientItem&)(rOriginalSet.Get(XATTR_FILLGRADIENT))).GetGradientValue());
258 			sal_uInt8 nStartLuminance(aGradient.GetStartColor().GetLuminance());
259 			sal_uInt8 nEndLuminance(aGradient.GetEndColor().GetLuminance());
260 
261 			if(aGradient.GetStartIntens() != 100)
262 			{
263 				nStartLuminance = (sal_uInt8)(nStartLuminance * ((double)aGradient.GetStartIntens() / 100.0));
264 			}
265 
266 			if(aGradient.GetEndIntens() != 100)
267 			{
268 				nEndLuminance = (sal_uInt8)(nEndLuminance * ((double)aGradient.GetEndIntens() / 100.0));
269 			}
270 
271             ::Color aStartColor(
272 				(sal_uInt8)((nStartLuminance * aShadowColor.GetRed()) / 256),
273 				(sal_uInt8)((nStartLuminance * aShadowColor.GetGreen()) / 256),
274 				(sal_uInt8)((nStartLuminance * aShadowColor.GetBlue()) / 256));
275 
276             ::Color aEndColor(
277 				(sal_uInt8)((nEndLuminance * aShadowColor.GetRed()) / 256),
278 				(sal_uInt8)((nEndLuminance * aShadowColor.GetGreen()) / 256),
279 				(sal_uInt8)((nEndLuminance * aShadowColor.GetBlue()) / 256));
280 
281 			aGradient.SetStartColor(aStartColor);
282 			aGradient.SetEndColor(aEndColor);
283 			aTempSet.Put(XFillGradientItem(aTempSet.GetPool(), aGradient));
284 			aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
285 		}
286 
287 		// hatch and transparence like shadow
288 		if(bHatchFillUsed)
289 		{
290 			XHatch aHatch(((XFillHatchItem&)(rOriginalSet.Get(XATTR_FILLHATCH))).GetHatchValue());
291 			aHatch.SetColor(aShadowColor);
292 			aTempSet.Put(XFillHatchItem(aTempSet.GetPool(), aHatch));
293 			aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
294 		}
295 
296 		// bitmap and transparence like shadow
297 		if(bBitmapFillUsed)
298 		{
299 			XOBitmap aFillBitmap(((XFillBitmapItem&)(rOriginalSet.Get(XATTR_FILLBITMAP))).GetBitmapValue());
300 			Bitmap aSourceBitmap(aFillBitmap.GetBitmap());
301 			BitmapReadAccess* pReadAccess = aSourceBitmap.AcquireReadAccess();
302 
303 			if(!aSourceBitmap.IsEmpty())
304 			{
305 				if(pReadAccess)
306 				{
307 					Bitmap aDestBitmap(aSourceBitmap.GetSizePixel(), 24L);
308 					BitmapWriteAccess* pWriteAccess = aDestBitmap.AcquireWriteAccess();
309 
310 					if(pWriteAccess)
311 					{
312 						for(sal_Int32 y(0L); y < pReadAccess->Height(); y++)
313 						{
314 							for(sal_Int32 x(0L); x < pReadAccess->Width(); x++)
315 							{
316 								sal_uInt16 nLuminance((sal_uInt16)pReadAccess->GetLuminance(y, x) + 1);
317 								const BitmapColor aDestColor(
318 									(sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetRed()) >> 8L),
319 									(sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetGreen()) >> 8L),
320 									(sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetBlue()) >> 8L));
321 								pWriteAccess->SetPixel(y, x, aDestColor);
322 							}
323 						}
324 
325 						aDestBitmap.ReleaseAccess(pWriteAccess);
326 						aFillBitmap.SetBitmap(aDestBitmap);
327 					}
328 
329 					aSourceBitmap.ReleaseAccess(pReadAccess);
330 				}
331 			}
332 
333 			aTempSet.Put(XFillBitmapItem(aTempSet.GetPool(), aFillBitmap));
334 			aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
335 		}
336 
337 		// set attributes and paint shadow object
338 		pRetval->SetMergedItemSet( aTempSet );
339 	}
340 	return pRetval;
341 }
342 
343 ////////////////////////////////////////////////////////////////////////////////////////////////////
344 
345 Reference< XCustomShapeEngine > SdrObjCustomShape::GetCustomShapeEngine( const SdrObjCustomShape* pCustomShape )
346 {
347 	Reference< XCustomShapeEngine > xCustomShapeEngine;
348 	String aEngine(((SdrCustomShapeEngineItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE )).GetValue());
349 	if ( !aEngine.Len() )
350 		aEngine = String( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.drawing.EnhancedCustomShapeEngine" ) );
351 
352 	Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
353 
354 	Reference< XShape > aXShape = GetXShapeForSdrObject( (SdrObjCustomShape*)pCustomShape );
355 	if ( aXShape.is() )
356 	{
357 		if ( aEngine.Len() && xFactory.is() )
358 		{
359 			Sequence< Any > aArgument( 1 );
360 			Sequence< PropertyValue > aPropValues( 1 );
361 			aPropValues[ 0 ].Name = rtl::OUString::createFromAscii( "CustomShape" );
362 			aPropValues[ 0 ].Value <<= aXShape;
363 			aArgument[ 0 ] <<= aPropValues;
364 			Reference< XInterface > xInterface( xFactory->createInstanceWithArguments( aEngine, aArgument ) );
365 			if ( xInterface.is() )
366 				xCustomShapeEngine = Reference< XCustomShapeEngine >( xInterface, UNO_QUERY );
367 		}
368 	}
369 	return xCustomShapeEngine;
370 }
371 const SdrObject* SdrObjCustomShape::GetSdrObjectFromCustomShape() const
372 {
373 	if ( !mXRenderedCustomShape.is() )
374 	{
375 		Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( this ) );
376 		if ( xCustomShapeEngine.is() )
377 			((SdrObjCustomShape*)this)->mXRenderedCustomShape = xCustomShapeEngine->render();
378 	}
379 	SdrObject* pRenderedCustomShape = mXRenderedCustomShape.is()
380 				? GetSdrObjectFromXShape( mXRenderedCustomShape )
381 				: NULL;
382 	return pRenderedCustomShape;
383 }
384 
385 // #i37011# Shadow geometry creation
386 const SdrObject* SdrObjCustomShape::GetSdrObjectShadowFromCustomShape() const
387 {
388 	if(!mpLastShadowGeometry)
389 	{
390 		const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
391 		if(pSdrObject)
392 		{
393 			const SfxItemSet& rOriginalSet = GetObjectItemSet();
394 			const sal_Bool bShadow(((SdrShadowItem&)rOriginalSet.Get( SDRATTR_SHADOW )).GetValue());
395 
396 			if(bShadow)
397 			{
398 				// create a clone with all attributes changed to shadow attributes
399 				// and translation executed, too.
400 				((SdrObjCustomShape*)this)->mpLastShadowGeometry = ImpCreateShadowObjectClone(*pSdrObject, rOriginalSet);
401 			}
402 		}
403 	}
404 
405 	return mpLastShadowGeometry;
406 }
407 
408 sal_Bool SdrObjCustomShape::IsTextPath() const
409 {
410 	const rtl::OUString	sTextPath( RTL_CONSTASCII_USTRINGPARAM ( "TextPath" ) );
411 	sal_Bool bTextPathOn = sal_False;
412 	SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
413 	Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath );
414 	if ( pAny )
415 		*pAny >>= bTextPathOn;
416 	return bTextPathOn;
417 }
418 
419 sal_Bool SdrObjCustomShape::UseNoFillStyle() const
420 {
421 	sal_Bool bRet = sal_False;
422 	rtl::OUString sShapeType;
423 	const rtl::OUString	sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
424 	SdrCustomShapeGeometryItem& rGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
425 	Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
426 	if ( pAny )
427 		*pAny >>= sShapeType;
428 	bRet = IsCustomShapeFilledByDefault( EnhancedCustomShapeTypeNames::Get( sType ) ) == 0;
429 
430 	return bRet;
431 }
432 
433 sal_Bool SdrObjCustomShape::IsMirroredX() const
434 {
435 	sal_Bool bMirroredX = sal_False;
436 	SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
437 	const rtl::OUString	sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) );
438 	com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX );
439 	if ( pAny )
440 		*pAny >>= bMirroredX;
441 	return bMirroredX;
442 }
443 sal_Bool SdrObjCustomShape::IsMirroredY() const
444 {
445 	sal_Bool bMirroredY = sal_False;
446 	SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
447 	const rtl::OUString	sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) );
448 	com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY );
449 	if ( pAny )
450 		*pAny >>= bMirroredY;
451 	return bMirroredY;
452 }
453 void SdrObjCustomShape::SetMirroredX( const sal_Bool bMirrorX )
454 {
455 	SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
456 	const rtl::OUString	sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) );
457 	//com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX );
458 	PropertyValue aPropVal;
459 	aPropVal.Name = sMirroredX;
460 	aPropVal.Value <<= bMirrorX;
461 	aGeometryItem.SetPropertyValue( aPropVal );
462 	SetMergedItem( aGeometryItem );
463 }
464 void SdrObjCustomShape::SetMirroredY( const sal_Bool bMirrorY )
465 {
466 	SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
467 	const rtl::OUString	sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) );
468 	//com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY );
469 	PropertyValue aPropVal;
470 	aPropVal.Name = sMirroredY;
471 	aPropVal.Value <<= bMirrorY;
472 	aGeometryItem.SetPropertyValue( aPropVal );
473 	SetMergedItem( aGeometryItem );
474 }
475 
476 double SdrObjCustomShape::GetObjectRotation() const
477 {
478 	return fObjectRotation;
479 }
480 
481 double SdrObjCustomShape::GetExtraTextRotation() const
482 {
483 	const com::sun::star::uno::Any* pAny;
484 	SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
485 	const rtl::OUString sTextRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) );
486 	pAny = rGeometryItem.GetPropertyValueByName( sTextRotateAngle );
487 	double fExtraTextRotateAngle = 0.0;
488 	if ( pAny )
489 		*pAny >>= fExtraTextRotateAngle;
490 	return fExtraTextRotateAngle;
491 }
492 sal_Bool SdrObjCustomShape::GetTextBounds( Rectangle& rTextBound ) const
493 {
494 	sal_Bool bRet = sal_False;
495 	Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( this ) );	// a candidate for being cached
496 	if ( xCustomShapeEngine.is() )
497 	{
498 		awt::Rectangle aR( xCustomShapeEngine->getTextBounds() );
499 		if ( aR.Width || aR.Height )
500 		{
501 			rTextBound = Rectangle( Point( aR.X, aR.Y ), Size( aR.Width, aR.Height ) );
502 			bRet = sal_True;
503 		}
504 	}
505 	return bRet;
506 }
507 basegfx::B2DPolyPolygon SdrObjCustomShape::GetLineGeometry( const SdrObjCustomShape* pCustomShape, const sal_Bool bBezierAllowed )
508 {
509 	basegfx::B2DPolyPolygon aRetval;
510 	sal_Bool bRet = sal_False;
511 	Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( pCustomShape ) );
512 	if ( xCustomShapeEngine.is() )
513 	{
514 		com::sun::star::drawing::PolyPolygonBezierCoords aBezierCoords = xCustomShapeEngine->getLineGeometry();
515 		try
516 		{
517 			aRetval = SvxConvertPolyPolygonBezierToB2DPolyPolygon( &aBezierCoords );
518 			if ( !bBezierAllowed && aRetval.areControlPointsUsed())
519 			{
520 				aRetval = basegfx::tools::adaptiveSubdivideByAngle(aRetval);
521 			}
522 			bRet = sal_True;
523 		}
524 		catch ( const com::sun::star::lang::IllegalArgumentException )
525 		{
526 		}
527 	}
528 	return aRetval;
529 }
530 
531 std::vector< SdrCustomShapeInteraction > SdrObjCustomShape::GetInteractionHandles( const SdrObjCustomShape* pCustomShape ) const
532 {
533 	std::vector< SdrCustomShapeInteraction > xRet;
534 	try
535 	{
536 		Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( pCustomShape ) );
537 		if ( xCustomShapeEngine.is() )
538 		{
539 			int i;
540 			Sequence< Reference< XCustomShapeHandle > > xInteractionHandles( xCustomShapeEngine->getInteraction() );
541 			for ( i = 0; i < xInteractionHandles.getLength(); i++ )
542 			{
543 				if ( xInteractionHandles[ i ].is() )
544 				{
545 					SdrCustomShapeInteraction aSdrCustomShapeInteraction;
546 					aSdrCustomShapeInteraction.xInteraction = xInteractionHandles[ i ];
547 					aSdrCustomShapeInteraction.aPosition = xInteractionHandles[ i ]->getPosition();
548 
549 					sal_Int32 nMode = 0;
550 					switch( ImpGetCustomShapeType( *this ) )
551 					{
552 						case mso_sptAccentBorderCallout90 :		// 2 ortho
553 						{
554 							if ( !i )
555 								nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
556 							else if ( i == 1)
557 								nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE | CUSTOMSHAPE_HANDLE_ORTHO4;
558 						}
559 						break;
560 
561 						case mso_sptWedgeRectCallout :
562 						case mso_sptWedgeRRectCallout :
563 						case mso_sptCloudCallout :
564 						case mso_sptWedgeEllipseCallout :
565 						{
566 							if ( !i )
567 								nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED;
568 						}
569 						break;
570 
571 						case mso_sptBorderCallout1 :			// 2 diag
572 						{
573 							if ( !i )
574 								nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
575 							else if ( i == 1 )
576 								nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE;
577 						}
578 						break;
579 						case mso_sptBorderCallout2 :			// 3
580 						{
581 							if ( !i )
582 								nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
583 							else if ( i == 2 )
584 								nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE;
585 						}
586 						break;
587 						case mso_sptCallout90 :
588 						case mso_sptAccentCallout90 :
589 						case mso_sptBorderCallout90 :
590 						case mso_sptCallout1 :
591 						case mso_sptCallout2 :
592 						case mso_sptCallout3 :
593 						case mso_sptAccentCallout1 :
594 						case mso_sptAccentCallout2 :
595 						case mso_sptAccentCallout3 :
596 						case mso_sptBorderCallout3 :
597 						case mso_sptAccentBorderCallout1 :
598 						case mso_sptAccentBorderCallout2 :
599 						case mso_sptAccentBorderCallout3 :
600 						{
601 							if ( !i )
602 								nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
603 						}
604 						break;
605 						default: break;
606 					}
607 					aSdrCustomShapeInteraction.nMode = nMode;
608 					xRet.push_back( aSdrCustomShapeInteraction );
609 				}
610 			}
611 		}
612 	}
613 	catch( const uno::RuntimeException& )
614 	{
615 	}
616 	return xRet;
617 }
618 
619 //////////////////////////////////////////////////////////////////////////////
620 // BaseProperties section
621 #define	DEFAULT_MINIMUM_SIGNED_COMPARE	((sal_Int32)0x80000000)
622 #define	DEFAULT_MAXIMUM_SIGNED_COMPARE	((sal_Int32)0x7fffffff)
623 
624 sdr::properties::BaseProperties* SdrObjCustomShape::CreateObjectSpecificProperties()
625 {
626 	return new sdr::properties::CustomShapeProperties(*this);
627 }
628 
629 TYPEINIT1(SdrObjCustomShape,SdrTextObj);
630 SdrObjCustomShape::SdrObjCustomShape() :
631 	SdrTextObj(),
632 	fObjectRotation( 0.0 ),
633 	mpLastShadowGeometry(0L)
634 {
635 	bTextFrame = sal_True;
636 }
637 
638 SdrObjCustomShape::~SdrObjCustomShape()
639 {
640 	// delete buffered display geometry
641 	InvalidateRenderGeometry();
642 }
643 
644 void SdrObjCustomShape::MergeDefaultAttributes( const rtl::OUString* pType )
645 {
646 	PropertyValue aPropVal;
647 	rtl::OUString sShapeType;
648 	const rtl::OUString	sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
649 	SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
650 	if ( pType && pType->getLength() )
651 	{
652 		sal_Int32 nType = pType->toInt32();
653 		if ( nType )
654 			sShapeType = EnhancedCustomShapeTypeNames::Get( static_cast< MSO_SPT >( nType ) );
655 		else
656 			sShapeType = *pType;
657 
658 		aPropVal.Name = sType;
659 		aPropVal.Value <<= sShapeType;
660 		aGeometryItem.SetPropertyValue( aPropVal );
661 	}
662 	else
663 	{
664 		Any *pAny = aGeometryItem.GetPropertyValueByName( sType );
665 		if ( pAny )
666 			*pAny >>= sShapeType;
667 	}
668 	MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
669 
670 	const sal_Int32* pDefData = NULL;
671 	const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
672 	if ( pDefCustomShape )
673 		pDefData = pDefCustomShape->pDefData;
674 
675 	com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > seqAdjustmentValues;
676 
677 	//////////////////////
678 	// AdjustmentValues //
679 	//////////////////////
680 	const rtl::OUString	sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) );
681 	const Any* pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sAdjustmentValues );
682 	if ( pAny )
683 		*pAny >>= seqAdjustmentValues;
684 	if ( pDefCustomShape && pDefData )	// now check if we have to default some adjustment values
685 	{
686 		// first check if there are adjustment values are to be appended
687 		sal_Int32 i, nAdjustmentValues = seqAdjustmentValues.getLength();
688 		sal_Int32 nAdjustmentDefaults = *pDefData++;
689 		if ( nAdjustmentDefaults > nAdjustmentValues )
690 		{
691 			seqAdjustmentValues.realloc( nAdjustmentDefaults );
692 			for ( i = nAdjustmentValues; i < nAdjustmentDefaults; i++ )
693 			{
694 				seqAdjustmentValues[ i ].Value <<= pDefData[ i ];
695 				seqAdjustmentValues[ i ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;	// com::sun::star::beans::PropertyState_DEFAULT_VALUE;
696 			}
697 		}
698 		// check if there are defaulted adjustment values that should be filled the hard coded defaults (pDefValue)
699 		sal_Int32 nCount = nAdjustmentValues > nAdjustmentDefaults ? nAdjustmentDefaults : nAdjustmentValues;
700 		for ( i = 0; i < nCount; i++ )
701 		{
702 			if ( seqAdjustmentValues[ i ].State != com::sun::star::beans::PropertyState_DIRECT_VALUE )
703 			{
704 				seqAdjustmentValues[ i ].Value <<= pDefData[ i ];
705 				seqAdjustmentValues[ i ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
706 			}
707 		}
708 	}
709 	aPropVal.Name = sAdjustmentValues;
710 	aPropVal.Value <<= seqAdjustmentValues;
711 	aGeometryItem.SetPropertyValue( aPropVal );
712 
713 	///////////////
714 	// Coordsize //
715 	///////////////
716 	const rtl::OUString	sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) );
717 	const Any* pViewBox = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sViewBox );
718 	com::sun::star::awt::Rectangle aViewBox;
719 	if ( !pViewBox || !(*pViewBox >>= aViewBox ) )
720 	{
721 		if ( pDefCustomShape )
722 		{
723 			aViewBox.X = 0;
724 			aViewBox.Y = 0;
725 			aViewBox.Width = pDefCustomShape->nCoordWidth;
726 			aViewBox.Height= pDefCustomShape->nCoordHeight;
727 			aPropVal.Name = sViewBox;
728 			aPropVal.Value <<= aViewBox;
729 			aGeometryItem.SetPropertyValue( aPropVal );
730 		}
731 	}
732 
733 	const rtl::OUString	sPath( RTL_CONSTASCII_USTRINGPARAM ( "Path" ) );
734 
735 	//////////////////////
736 	// Path/Coordinates //
737 	//////////////////////
738 	const rtl::OUString	sCoordinates( RTL_CONSTASCII_USTRINGPARAM ( "Coordinates" ) );
739 	pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sCoordinates );
740 	if ( !pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices )
741 	{
742 		com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates;
743 
744 		sal_Int32 i, nCount = pDefCustomShape->nVertices;
745 		seqCoordinates.realloc( nCount );
746 		for ( i = 0; i < nCount; i++ )
747 		{
748 			EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates[ i ].First, pDefCustomShape->pVertices[ i ].nValA );
749 			EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates[ i ].Second, pDefCustomShape->pVertices[ i ].nValB );
750 		}
751 		aPropVal.Name = sCoordinates;
752 		aPropVal.Value <<= seqCoordinates;
753 		aGeometryItem.SetPropertyValue( sPath, aPropVal );
754 	}
755 
756 	/////////////////////
757 	// Path/GluePoints //
758 	/////////////////////
759 	const rtl::OUString	sGluePoints( RTL_CONSTASCII_USTRINGPARAM ( "GluePoints" ) );
760 	pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sGluePoints );
761 	if ( !pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints )
762 	{
763 		com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqGluePoints;
764 		sal_Int32 i, nCount = pDefCustomShape->nGluePoints;
765 		seqGluePoints.realloc( nCount );
766 		for ( i = 0; i < nCount; i++ )
767 		{
768 			EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA );
769 			EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB );
770 		}
771 		aPropVal.Name = sGluePoints;
772 		aPropVal.Value <<= seqGluePoints;
773 		aGeometryItem.SetPropertyValue( sPath, aPropVal );
774 	}
775 
776 	///////////////////
777 	// Path/Segments //
778 	///////////////////
779 	const rtl::OUString	sSegments( RTL_CONSTASCII_USTRINGPARAM ( "Segments" ) );
780 	pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sSegments );
781 	if ( !pAny && pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements )
782 	{
783 		com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments;
784 
785 		sal_Int32 i, nCount = pDefCustomShape->nElements;
786 		seqSegments.realloc( nCount );
787 		for ( i = 0; i < nCount; i++ )
788 		{
789 			EnhancedCustomShapeSegment& rSegInfo = seqSegments[ i ];
790 			sal_uInt16 nSDat = pDefCustomShape->pElements[ i ];
791 			switch( nSDat >> 8 )
792 			{
793 				case 0x00 :
794 				{
795 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::LINETO;
796 					rSegInfo.Count   = nSDat & 0xff;
797 					if ( !rSegInfo.Count )
798 						rSegInfo.Count = 1;
799 				}
800 				break;
801 				case 0x20 :
802 				{
803 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CURVETO;
804 					rSegInfo.Count   = nSDat & 0xff;
805 					if ( !rSegInfo.Count )
806 						rSegInfo.Count = 1;
807 				}
808 				break;
809 				case 0x40 :
810 				{
811 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::MOVETO;
812 					rSegInfo.Count   = nSDat & 0xff;
813 					if ( !rSegInfo.Count )
814 						rSegInfo.Count = 1;
815 				}
816 				break;
817 				case 0x60 :
818 				{
819 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
820 					rSegInfo.Count   = 0;
821 				}
822 				break;
823 				case 0x80 :
824 				{
825 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
826 					rSegInfo.Count   = 0;
827 				}
828 				break;
829 				case 0xa1 :
830 				{
831 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO;
832 					rSegInfo.Count   = ( nSDat & 0xff ) / 3;
833 				}
834 				break;
835 				case 0xa2 :
836 				{
837 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE;
838 					rSegInfo.Count   = ( nSDat & 0xff ) / 3;
839 				}
840 				break;
841 				case 0xa3 :
842 				{
843 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARCTO;
844 					rSegInfo.Count   = ( nSDat & 0xff ) >> 2;
845 				}
846 				break;
847 				case 0xa4 :
848 				{
849 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARC;
850 					rSegInfo.Count   = ( nSDat & 0xff ) >> 2;
851 				}
852 				break;
853 				case 0xa5 :
854 				{
855 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO;
856 					rSegInfo.Count   = ( nSDat & 0xff ) >> 2;
857 				}
858 				break;
859 				case 0xa6 :
860 				{
861 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC;
862 					rSegInfo.Count   = ( nSDat & 0xff ) >> 2;
863 				}
864 				break;
865 				case 0xa7 :
866 				{
867 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX;
868 					rSegInfo.Count   = nSDat & 0xff;
869 				}
870 				break;
871 				case 0xa8 :
872 				{
873 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY;
874 					rSegInfo.Count   = nSDat & 0xff;
875 				}
876 				break;
877 				case 0xaa :
878 				{
879 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOFILL;
880 					rSegInfo.Count   = 0;
881 				}
882 				break;
883 				case 0xab :
884 				{
885 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOSTROKE;
886 					rSegInfo.Count   = 0;
887 				}
888 				break;
889 				default:
890 				case 0xf8 :
891 				{
892 					rSegInfo.Command = EnhancedCustomShapeSegmentCommand::UNKNOWN;
893 					rSegInfo.Count   = nSDat;
894 				}
895 				break;
896 			}
897 		}
898 		aPropVal.Name = sSegments;
899 		aPropVal.Value <<= seqSegments;
900 		aGeometryItem.SetPropertyValue( sPath, aPropVal );
901 	}
902 
903 	///////////////////
904 	// Path/StretchX //
905 	///////////////////
906 	const rtl::OUString	sStretchX( RTL_CONSTASCII_USTRINGPARAM ( "StretchX" ) );
907 	pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchX );
908 	if ( !pAny && pDefCustomShape )
909 	{
910 		sal_Int32 nXRef = pDefCustomShape->nXRef;
911 		if ( ( nXRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) )
912 		{
913 			aPropVal.Name = sStretchX;
914 			aPropVal.Value <<= nXRef;
915 			aGeometryItem.SetPropertyValue( sPath, aPropVal );
916 		}
917 	}
918 
919 	///////////////////
920 	// Path/StretchY //
921 	///////////////////
922 	const rtl::OUString	sStretchY( RTL_CONSTASCII_USTRINGPARAM ( "StretchY" ) );
923 	pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchY );
924 	if ( !pAny && pDefCustomShape )
925 	{
926 		sal_Int32 nYRef = pDefCustomShape->nYRef;
927 		if ( ( nYRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) )
928 		{
929 			aPropVal.Name = sStretchY;
930 			aPropVal.Value <<= nYRef;
931 			aGeometryItem.SetPropertyValue( sPath, aPropVal );
932 		}
933 	}
934 
935 	/////////////////////
936 	// Path/TextFrames //
937 	/////////////////////
938 	const rtl::OUString	sTextFrames( RTL_CONSTASCII_USTRINGPARAM ( "TextFrames" ) );
939 	pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sTextFrames );
940 	if ( !pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect )
941 	{
942 		com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > seqTextFrames;
943 
944 		sal_Int32 i, nCount = pDefCustomShape->nTextRect;
945 		seqTextFrames.realloc( nCount );
946 		const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect;
947 		for ( i = 0; i < nCount; i++, pRectangles++ )
948 		{
949 			EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].TopLeft.First,	  pRectangles->nPairA.nValA );
950 			EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].TopLeft.Second,	  pRectangles->nPairA.nValB );
951 			EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].BottomRight.First,  pRectangles->nPairB.nValA );
952 			EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].BottomRight.Second, pRectangles->nPairB.nValB );
953 		}
954 		aPropVal.Name = sTextFrames;
955 		aPropVal.Value <<= seqTextFrames;
956 		aGeometryItem.SetPropertyValue( sPath, aPropVal );
957 	}
958 
959 	///////////////
960 	// Equations //
961 	///////////////
962 	const rtl::OUString	sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) );
963 	pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sEquations );
964 	if ( !pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation )
965 	{
966 		com::sun::star::uno::Sequence< rtl::OUString > seqEquations;
967 
968 		sal_Int32 i, nCount = pDefCustomShape->nCalculation;
969 		seqEquations.realloc( nCount );
970 		const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation;
971 		for ( i = 0; i < nCount; i++, pData++ )
972 			seqEquations[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] );
973 		aPropVal.Name = sEquations;
974 		aPropVal.Value <<= seqEquations;
975 		aGeometryItem.SetPropertyValue( aPropVal );
976 	}
977 
978 	/////////////
979 	// Handles //
980 	/////////////
981 	const rtl::OUString	sHandles( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) );
982 	pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sHandles );
983 	if ( !pAny && pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
984 	{
985 		com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValues > seqHandles;
986 
987 		sal_Int32 i, n, nCount = pDefCustomShape->nHandles;
988 		const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
989 		seqHandles.realloc( nCount );
990 		for ( i = 0; i < nCount; i++, pData++ )
991 		{
992 			sal_Int32 nPropertiesNeeded = 1;	// position is always needed
993 			sal_Int32 nFlags = pData->nFlags;
994 			if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X )
995 				nPropertiesNeeded++;
996 			if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y )
997 				nPropertiesNeeded++;
998 			if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED )
999 				nPropertiesNeeded++;
1000 			if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR )
1001 			{
1002 				nPropertiesNeeded++;
1003 				if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE )
1004 				{
1005 					if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1006 						nPropertiesNeeded++;
1007 					if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1008 						nPropertiesNeeded++;
1009 				}
1010 			}
1011 			else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE )
1012 			{
1013 				if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1014 					nPropertiesNeeded++;
1015 				if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1016 					nPropertiesNeeded++;
1017 				if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1018 					nPropertiesNeeded++;
1019 				if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1020 					nPropertiesNeeded++;
1021 			}
1022 
1023 			n = 0;
1024 			com::sun::star::beans::PropertyValues& rPropValues = seqHandles[ i ];
1025 			rPropValues.realloc( nPropertiesNeeded );
1026 
1027 			// POSITION
1028 			{
1029 				const rtl::OUString	sPosition( RTL_CONSTASCII_USTRINGPARAM ( "Position" ) );
1030 				::com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition;
1031 				EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, pData->nPositionX, sal_True, sal_True );
1032 				EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, pData->nPositionY, sal_True, sal_False );
1033 				rPropValues[ n ].Name = sPosition;
1034 				rPropValues[ n++ ].Value <<= aPosition;
1035 			}
1036 			if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X )
1037 			{
1038 				const rtl::OUString	sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) );
1039 				sal_Bool bMirroredX = sal_True;
1040 				rPropValues[ n ].Name = sMirroredX;
1041 				rPropValues[ n++ ].Value <<= bMirroredX;
1042 			}
1043 			if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y )
1044 			{
1045 				const rtl::OUString	sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) );
1046 				sal_Bool bMirroredY = sal_True;
1047 				rPropValues[ n ].Name = sMirroredY;
1048 				rPropValues[ n++ ].Value <<= bMirroredY;
1049 			}
1050 			if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED )
1051 			{
1052 				const rtl::OUString	sSwitched( RTL_CONSTASCII_USTRINGPARAM ( "Switched" ) );
1053 				sal_Bool bSwitched = sal_True;
1054 				rPropValues[ n ].Name = sSwitched;
1055 				rPropValues[ n++ ].Value <<= bSwitched;
1056 			}
1057 			if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR )
1058 			{
1059 				const rtl::OUString	sPolar( RTL_CONSTASCII_USTRINGPARAM ( "Polar" ) );
1060 				::com::sun::star::drawing::EnhancedCustomShapeParameterPair aCenter;
1061 				EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.First,  pData->nCenterX,
1062 					( nFlags & MSDFF_HANDLE_FLAGS_CENTER_X_IS_SPECIAL ) != 0, sal_True  );
1063 				EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.Second, pData->nCenterY,
1064 					( nFlags & MSDFF_HANDLE_FLAGS_CENTER_Y_IS_SPECIAL ) != 0, sal_False );
1065 				rPropValues[ n ].Name = sPolar;
1066 				rPropValues[ n++ ].Value <<= aCenter;
1067 				if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE )
1068 				{
1069 					if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1070 					{
1071 						const rtl::OUString	sRadiusRangeMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMinimum" ) );
1072 						::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
1073 						EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, pData->nRangeXMin,
1074 							( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True  );
1075 						rPropValues[ n ].Name = sRadiusRangeMinimum;
1076 						rPropValues[ n++ ].Value <<= aRadiusRangeMinimum;
1077 					}
1078 					if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1079 					{
1080 						const rtl::OUString	sRadiusRangeMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMaximum" ) );
1081 						::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
1082 						EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, pData->nRangeXMax,
1083 							( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False );
1084 						rPropValues[ n ].Name = sRadiusRangeMaximum;
1085 						rPropValues[ n++ ].Value <<= aRadiusRangeMaximum;
1086 					}
1087 				}
1088 			}
1089 			else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE )
1090 			{
1091 				if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1092 				{
1093 					const rtl::OUString	sRangeXMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMinimum" ) );
1094 					::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMinimum;
1095 					EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, pData->nRangeXMin,
1096 						( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True  );
1097 					rPropValues[ n ].Name = sRangeXMinimum;
1098 					rPropValues[ n++ ].Value <<= aRangeXMinimum;
1099 				}
1100 				if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1101 				{
1102 					const rtl::OUString	sRangeXMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMaximum" ) );
1103 					::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMaximum;
1104 					EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, pData->nRangeXMax,
1105 						( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False );
1106 					rPropValues[ n ].Name = sRangeXMaximum;
1107 					rPropValues[ n++ ].Value <<= aRangeXMaximum;
1108 				}
1109 				if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1110 				{
1111 					const rtl::OUString	sRangeYMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMinimum" ) );
1112 					::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMinimum;
1113 					EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, pData->nRangeYMin,
1114 						( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MIN_IS_SPECIAL ) != 0, sal_True );
1115 					rPropValues[ n ].Name = sRangeYMinimum;
1116 					rPropValues[ n++ ].Value <<= aRangeYMinimum;
1117 				}
1118 				if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1119 				{
1120 					const rtl::OUString	sRangeYMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMaximum" ) );
1121 					::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMaximum;
1122 					EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, pData->nRangeYMax,
1123 						( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MAX_IS_SPECIAL ) != 0, sal_False );
1124 					rPropValues[ n ].Name = sRangeYMaximum;
1125 					rPropValues[ n++ ].Value <<= aRangeYMaximum;
1126 				}
1127 			}
1128 		}
1129 		aPropVal.Name = sHandles;
1130 		aPropVal.Value <<= seqHandles;
1131 		aGeometryItem.SetPropertyValue( aPropVal );
1132 	}
1133 	SetMergedItem( aGeometryItem );
1134 }
1135 
1136 sal_Bool SdrObjCustomShape::IsDefaultGeometry( const DefaultType eDefaultType ) const
1137 {
1138 	sal_Bool bIsDefaultGeometry = sal_False;
1139 
1140 	PropertyValue aPropVal;
1141 	rtl::OUString sShapeType;
1142 	const rtl::OUString	sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
1143 	SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
1144 
1145 	Any *pAny = aGeometryItem.GetPropertyValueByName( sType );
1146 	if ( pAny )
1147 		*pAny >>= sShapeType;
1148 
1149 	MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
1150 
1151 	const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
1152 	const rtl::OUString	sPath( RTL_CONSTASCII_USTRINGPARAM ( "Path" ) );
1153 	switch( eDefaultType )
1154 	{
1155 		case DEFAULT_VIEWBOX :
1156 		{
1157 			const rtl::OUString	sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) );
1158 			const Any* pViewBox = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sViewBox );
1159 			com::sun::star::awt::Rectangle aViewBox;
1160 			if ( pViewBox && ( *pViewBox >>= aViewBox ) )
1161 			{
1162 				if ( ( aViewBox.Width == pDefCustomShape->nCoordWidth )
1163 					&& ( aViewBox.Height == pDefCustomShape->nCoordHeight ) )
1164 					bIsDefaultGeometry = sal_True;
1165 			}
1166 		}
1167 		break;
1168 
1169 		case DEFAULT_PATH :
1170 		{
1171 			const rtl::OUString	sCoordinates( RTL_CONSTASCII_USTRINGPARAM ( "Coordinates" ) );
1172 			pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sCoordinates );
1173 			if ( pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices )
1174 			{
1175 				com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates1, seqCoordinates2;
1176 				if ( *pAny >>= seqCoordinates1 )
1177 				{
1178 					sal_Int32 i, nCount = pDefCustomShape->nVertices;
1179 					seqCoordinates2.realloc( nCount );
1180 					for ( i = 0; i < nCount; i++ )
1181 					{
1182 						EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ i ].First, pDefCustomShape->pVertices[ i ].nValA );
1183 						EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ i ].Second, pDefCustomShape->pVertices[ i ].nValB );
1184 					}
1185 					if ( seqCoordinates1 == seqCoordinates2 )
1186 						bIsDefaultGeometry = sal_True;
1187 				}
1188 			}
1189 			else if ( pDefCustomShape && ( ( pDefCustomShape->nVertices == 0 ) || ( pDefCustomShape->pVertices == 0 ) ) )
1190 				bIsDefaultGeometry = sal_True;
1191 		}
1192 		break;
1193 
1194 		case DEFAULT_GLUEPOINTS :
1195 		{
1196 			const rtl::OUString	sGluePoints( RTL_CONSTASCII_USTRINGPARAM ( "GluePoints" ) );
1197 			pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sGluePoints );
1198 			if ( pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints )
1199 			{
1200 				com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqGluePoints1, seqGluePoints2;
1201 				if ( *pAny >>= seqGluePoints1 )
1202 				{
1203 					sal_Int32 i, nCount = pDefCustomShape->nGluePoints;
1204 					seqGluePoints2.realloc( nCount );
1205 					for ( i = 0; i < nCount; i++ )
1206 					{
1207 						EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints2[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA );
1208 						EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints2[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB );
1209 					}
1210 					if ( seqGluePoints1 == seqGluePoints2 )
1211 						bIsDefaultGeometry = sal_True;
1212 				}
1213 			}
1214 			else if ( pDefCustomShape && ( pDefCustomShape->nGluePoints == 0 ) )
1215 				bIsDefaultGeometry = sal_True;
1216 		}
1217 		break;
1218 
1219 		case DEFAULT_SEGMENTS :
1220 		{
1221 			///////////////////
1222 			// Path/Segments //
1223 			///////////////////
1224 			const rtl::OUString	sSegments( RTL_CONSTASCII_USTRINGPARAM ( "Segments" ) );
1225 			pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sSegments );
1226 			if ( pAny )
1227 			{
1228 				com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments1, seqSegments2;
1229 				if ( *pAny >>= seqSegments1 )
1230 				{
1231 					if ( pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements )
1232 					{
1233 						sal_Int32 i, nCount = pDefCustomShape->nElements;
1234 						if ( nCount )
1235 						{
1236 							seqSegments2.realloc( nCount );
1237 							for ( i = 0; i < nCount; i++ )
1238 							{
1239 								EnhancedCustomShapeSegment& rSegInfo = seqSegments2[ i ];
1240 								sal_uInt16 nSDat = pDefCustomShape->pElements[ i ];
1241 								switch( nSDat >> 8 )
1242 								{
1243 									case 0x00 :
1244 									{
1245 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::LINETO;
1246 										rSegInfo.Count   = nSDat & 0xff;
1247 										if ( !rSegInfo.Count )
1248 											rSegInfo.Count = 1;
1249 									}
1250 									break;
1251 									case 0x20 :
1252 									{
1253 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CURVETO;
1254 										rSegInfo.Count   = nSDat & 0xff;
1255 										if ( !rSegInfo.Count )
1256 											rSegInfo.Count = 1;
1257 									}
1258 									break;
1259 									case 0x40 :
1260 									{
1261 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::MOVETO;
1262 										rSegInfo.Count   = nSDat & 0xff;
1263 										if ( !rSegInfo.Count )
1264 											rSegInfo.Count = 1;
1265 									}
1266 									break;
1267 									case 0x60 :
1268 									{
1269 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
1270 										rSegInfo.Count   = 0;
1271 									}
1272 									break;
1273 									case 0x80 :
1274 									{
1275 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
1276 										rSegInfo.Count   = 0;
1277 									}
1278 									break;
1279 									case 0xa1 :
1280 									{
1281 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO;
1282 										rSegInfo.Count   = ( nSDat & 0xff ) / 3;
1283 									}
1284 									break;
1285 									case 0xa2 :
1286 									{
1287 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE;
1288 										rSegInfo.Count   = ( nSDat & 0xff ) / 3;
1289 									}
1290 									break;
1291 									case 0xa3 :
1292 									{
1293 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARCTO;
1294 										rSegInfo.Count   = ( nSDat & 0xff ) >> 2;
1295 									}
1296 									break;
1297 									case 0xa4 :
1298 									{
1299 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARC;
1300 										rSegInfo.Count   = ( nSDat & 0xff ) >> 2;
1301 									}
1302 									break;
1303 									case 0xa5 :
1304 									{
1305 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO;
1306 										rSegInfo.Count   = ( nSDat & 0xff ) >> 2;
1307 									}
1308 									break;
1309 									case 0xa6 :
1310 									{
1311 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC;
1312 										rSegInfo.Count   = ( nSDat & 0xff ) >> 2;
1313 									}
1314 									break;
1315 									case 0xa7 :
1316 									{
1317 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX;
1318 										rSegInfo.Count   = nSDat & 0xff;
1319 									}
1320 									break;
1321 									case 0xa8 :
1322 									{
1323 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY;
1324 										rSegInfo.Count   = nSDat & 0xff;
1325 									}
1326 									break;
1327 									case 0xaa :
1328 									{
1329 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOFILL;
1330 										rSegInfo.Count   = 0;
1331 									}
1332 									break;
1333 									case 0xab :
1334 									{
1335 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOSTROKE;
1336 										rSegInfo.Count   = 0;
1337 									}
1338 									break;
1339 									default:
1340 									case 0xf8 :
1341 									{
1342 										rSegInfo.Command = EnhancedCustomShapeSegmentCommand::UNKNOWN;
1343 										rSegInfo.Count   = nSDat;
1344 									}
1345 									break;
1346 								}
1347 							}
1348 							if ( seqSegments1 == seqSegments2 )
1349 								bIsDefaultGeometry = sal_True;
1350 						}
1351 					}
1352 					else
1353 					{
1354 						// check if its the default segment description	( M L Z N )
1355 						if ( seqSegments1.getLength() == 4 )
1356 						{
1357 							if ( ( seqSegments1[ 0 ].Command == EnhancedCustomShapeSegmentCommand::MOVETO )
1358 								&& ( seqSegments1[ 1 ].Command == EnhancedCustomShapeSegmentCommand::LINETO )
1359 								&& ( seqSegments1[ 2 ].Command == EnhancedCustomShapeSegmentCommand::CLOSESUBPATH )
1360 								&& ( seqSegments1[ 3 ].Command == EnhancedCustomShapeSegmentCommand::ENDSUBPATH ) )
1361 								bIsDefaultGeometry = sal_True;
1362 						}
1363 					}
1364 				}
1365 			}
1366 			else if ( pDefCustomShape && ( ( pDefCustomShape->nElements == 0 ) || ( pDefCustomShape->pElements == 0 ) ) )
1367 				bIsDefaultGeometry = sal_True;
1368 		}
1369 		break;
1370 
1371 		case DEFAULT_STRETCHX :
1372 		{
1373 			const rtl::OUString	sStretchX( RTL_CONSTASCII_USTRINGPARAM ( "StretchX" ) );
1374 			pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchX );
1375 			if ( pAny && pDefCustomShape )
1376 			{
1377 				sal_Int32 nStretchX = 0;
1378 				if ( *pAny >>= nStretchX )
1379 				{
1380 					if ( pDefCustomShape->nXRef == nStretchX )
1381 						bIsDefaultGeometry = sal_True;
1382 				}
1383 			}
1384 			else if ( pDefCustomShape && ( pDefCustomShape->nXRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1385 				bIsDefaultGeometry = sal_True;
1386 		}
1387 		break;
1388 
1389 		case DEFAULT_STRETCHY :
1390 		{
1391 			const rtl::OUString	sStretchY( RTL_CONSTASCII_USTRINGPARAM ( "StretchY" ) );
1392 			pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchY );
1393 			if ( pAny && pDefCustomShape )
1394 			{
1395 				sal_Int32 nStretchY = 0;
1396 				if ( *pAny >>= nStretchY )
1397 				{
1398 					if ( pDefCustomShape->nYRef == nStretchY )
1399 						bIsDefaultGeometry = sal_True;
1400 				}
1401 			}
1402 			else if ( pDefCustomShape && ( pDefCustomShape->nYRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1403 				bIsDefaultGeometry = sal_True;
1404 		}
1405 		break;
1406 
1407 		case DEFAULT_EQUATIONS :
1408 		{
1409 			const rtl::OUString	sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) );
1410 			pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sEquations );
1411 			if ( pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation )
1412 			{
1413 				com::sun::star::uno::Sequence< rtl::OUString > seqEquations1, seqEquations2;
1414 				if ( *pAny >>= seqEquations1 )
1415 				{
1416 					sal_Int32 i, nCount = pDefCustomShape->nCalculation;
1417 					seqEquations2.realloc( nCount );
1418 
1419 					const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation;
1420 					for ( i = 0; i < nCount; i++, pData++ )
1421 						seqEquations2[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] );
1422 
1423 					if ( seqEquations1 == seqEquations2 )
1424 						bIsDefaultGeometry = sal_True;
1425 				}
1426 			}
1427 			else if ( pDefCustomShape && ( ( pDefCustomShape->nCalculation == 0 ) || ( pDefCustomShape->pCalculation == 0 ) ) )
1428 				bIsDefaultGeometry = sal_True;
1429 		}
1430 		break;
1431 
1432 		case DEFAULT_TEXTFRAMES :
1433 		{
1434 			const rtl::OUString	sTextFrames( RTL_CONSTASCII_USTRINGPARAM( "TextFrames" ) );
1435 			pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sTextFrames );
1436 			if ( pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect )
1437 			{
1438 				com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > seqTextFrames1, seqTextFrames2;
1439 				if ( *pAny >>= seqTextFrames1 )
1440 				{
1441 					sal_Int32 i, nCount = pDefCustomShape->nTextRect;
1442 					seqTextFrames2.realloc( nCount );
1443 					const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect;
1444 					for ( i = 0; i < nCount; i++, pRectangles++ )
1445 					{
1446 						EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].TopLeft.First,	  pRectangles->nPairA.nValA );
1447 						EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].TopLeft.Second,	  pRectangles->nPairA.nValB );
1448 						EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].BottomRight.First,  pRectangles->nPairB.nValA );
1449 						EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].BottomRight.Second, pRectangles->nPairB.nValB );
1450 					}
1451 					if ( seqTextFrames1 == seqTextFrames2 )
1452 						bIsDefaultGeometry = sal_True;
1453 				}
1454 			}
1455 			else if ( pDefCustomShape && ( ( pDefCustomShape->nTextRect == 0 ) || ( pDefCustomShape->pTextRect == 0 ) ) )
1456 				bIsDefaultGeometry = sal_True;
1457 		}
1458 		break;
1459 
1460 		case DEFAULT_HANDLES :
1461 		{
1462 			const rtl::OUString	sHandles( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) );
1463 			pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sHandles );
1464 			if ( pAny && pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
1465 			{
1466 				com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValues > seqHandles1, seqHandles2;
1467 				if ( *pAny >>= seqHandles1 )
1468 				{
1469 					sal_Int32 i, n, nCount = pDefCustomShape->nHandles;
1470 					const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
1471 					seqHandles2.realloc( nCount );
1472 					for ( i = 0; i < nCount; i++, pData++ )
1473 					{
1474 						sal_Int32 nPropertiesNeeded = 1;	// position is always needed
1475 						sal_Int32 nFlags = pData->nFlags;
1476 						if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X )
1477 							nPropertiesNeeded++;
1478 						if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y )
1479 							nPropertiesNeeded++;
1480 						if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED )
1481 							nPropertiesNeeded++;
1482 						if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR )
1483 						{
1484 							nPropertiesNeeded++;
1485 							if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE )
1486 							{
1487 								if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1488 									nPropertiesNeeded++;
1489 								if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1490 									nPropertiesNeeded++;
1491 							}
1492 						}
1493 						else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE )
1494 						{
1495 							if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1496 								nPropertiesNeeded++;
1497 							if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1498 								nPropertiesNeeded++;
1499 							if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1500 								nPropertiesNeeded++;
1501 							if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1502 								nPropertiesNeeded++;
1503 						}
1504 
1505 						n = 0;
1506 						com::sun::star::beans::PropertyValues& rPropValues = seqHandles2[ i ];
1507 						rPropValues.realloc( nPropertiesNeeded );
1508 
1509 						// POSITION
1510 						{
1511 							const rtl::OUString	sPosition( RTL_CONSTASCII_USTRINGPARAM ( "Position" ) );
1512 							::com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition;
1513 							EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, pData->nPositionX, sal_True, sal_True );
1514 							EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, pData->nPositionY, sal_True, sal_False );
1515 							rPropValues[ n ].Name = sPosition;
1516 							rPropValues[ n++ ].Value <<= aPosition;
1517 						}
1518 						if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X )
1519 						{
1520 							const rtl::OUString	sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) );
1521 							sal_Bool bMirroredX = sal_True;
1522 							rPropValues[ n ].Name = sMirroredX;
1523 							rPropValues[ n++ ].Value <<= bMirroredX;
1524 						}
1525 						if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y )
1526 						{
1527 							const rtl::OUString	sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) );
1528 							sal_Bool bMirroredY = sal_True;
1529 							rPropValues[ n ].Name = sMirroredY;
1530 							rPropValues[ n++ ].Value <<= bMirroredY;
1531 						}
1532 						if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED )
1533 						{
1534 							const rtl::OUString	sSwitched( RTL_CONSTASCII_USTRINGPARAM ( "Switched" ) );
1535 							sal_Bool bSwitched = sal_True;
1536 							rPropValues[ n ].Name = sSwitched;
1537 							rPropValues[ n++ ].Value <<= bSwitched;
1538 						}
1539 						if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR )
1540 						{
1541 							const rtl::OUString	sPolar( RTL_CONSTASCII_USTRINGPARAM ( "Polar" ) );
1542 							::com::sun::star::drawing::EnhancedCustomShapeParameterPair aCenter;
1543 							EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.First,  pData->nCenterX,
1544 								( nFlags & MSDFF_HANDLE_FLAGS_CENTER_X_IS_SPECIAL ) != 0, sal_True  );
1545 							EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.Second, pData->nCenterY,
1546 								( nFlags & MSDFF_HANDLE_FLAGS_CENTER_Y_IS_SPECIAL ) != 0, sal_False );
1547 							rPropValues[ n ].Name = sPolar;
1548 							rPropValues[ n++ ].Value <<= aCenter;
1549 							if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE )
1550 							{
1551 								if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1552 								{
1553 									const rtl::OUString	sRadiusRangeMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMinimum" ) );
1554 									::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
1555 									EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, pData->nRangeXMin,
1556 										( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True  );
1557 									rPropValues[ n ].Name = sRadiusRangeMinimum;
1558 									rPropValues[ n++ ].Value <<= aRadiusRangeMinimum;
1559 								}
1560 								if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1561 								{
1562 									const rtl::OUString	sRadiusRangeMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMaximum" ) );
1563 									::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
1564 									EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, pData->nRangeXMax,
1565 										( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False );
1566 									rPropValues[ n ].Name = sRadiusRangeMaximum;
1567 									rPropValues[ n++ ].Value <<= aRadiusRangeMaximum;
1568 								}
1569 							}
1570 						}
1571 						else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE )
1572 						{
1573 							if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1574 							{
1575 								const rtl::OUString	sRangeXMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMinimum" ) );
1576 								::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMinimum;
1577 								EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, pData->nRangeXMin,
1578 									( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True  );
1579 								rPropValues[ n ].Name = sRangeXMinimum;
1580 								rPropValues[ n++ ].Value <<= aRangeXMinimum;
1581 							}
1582 							if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1583 							{
1584 								const rtl::OUString	sRangeXMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMaximum" ) );
1585 								::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMaximum;
1586 								EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, pData->nRangeXMax,
1587 									( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False );
1588 								rPropValues[ n ].Name = sRangeXMaximum;
1589 								rPropValues[ n++ ].Value <<= aRangeXMaximum;
1590 							}
1591 							if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
1592 							{
1593 								const rtl::OUString	sRangeYMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMinimum" ) );
1594 								::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMinimum;
1595 								EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, pData->nRangeYMin,
1596 									( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MIN_IS_SPECIAL ) != 0, sal_True );
1597 								rPropValues[ n ].Name = sRangeYMinimum;
1598 								rPropValues[ n++ ].Value <<= aRangeYMinimum;
1599 							}
1600 							if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
1601 							{
1602 								const rtl::OUString	sRangeYMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMaximum" ) );
1603 								::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMaximum;
1604 								EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, pData->nRangeYMax,
1605 									( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MAX_IS_SPECIAL ) != 0, sal_False );
1606 								rPropValues[ n ].Name = sRangeYMaximum;
1607 								rPropValues[ n++ ].Value <<= aRangeYMaximum;
1608 							}
1609 						}
1610 					}
1611 					if ( seqHandles1 == seqHandles2 )
1612 						bIsDefaultGeometry = sal_True;
1613 				}
1614 			}
1615 			else if ( pDefCustomShape && ( ( pDefCustomShape->nHandles == 0 ) || ( pDefCustomShape->pHandles == 0 ) ) )
1616 				bIsDefaultGeometry = sal_True;
1617 		}
1618 		break;
1619 	}
1620 	return bIsDefaultGeometry;
1621 }
1622 
1623 void SdrObjCustomShape::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
1624 {
1625 	rInfo.bResizeFreeAllowed=fObjectRotation == 0.0;
1626 	rInfo.bResizePropAllowed=sal_True;
1627 	rInfo.bRotateFreeAllowed=sal_True;
1628 	rInfo.bRotate90Allowed  =sal_True;
1629 	rInfo.bMirrorFreeAllowed=sal_True;
1630 	rInfo.bMirror45Allowed  =sal_True;
1631 	rInfo.bMirror90Allowed  =sal_True;
1632 	rInfo.bTransparenceAllowed = sal_False;
1633 	rInfo.bGradientAllowed = sal_False;
1634 	rInfo.bShearAllowed     =sal_True;
1635 	rInfo.bEdgeRadiusAllowed=sal_False;
1636 	rInfo.bNoContortion     =sal_True;
1637 
1638 	// #i37011#
1639 	if ( mXRenderedCustomShape.is() )
1640 	{
1641 		const SdrObject* pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape );
1642 		if ( pRenderedCustomShape )
1643 		{
1644 			// #i37262#
1645 			// Iterate self over the contained objects, since there are combinations of
1646 			// polygon and curve objects. In that case, aInfo.bCanConvToPath and
1647 			// aInfo.bCanConvToPoly would be false. What is needed here is an or, not an and.
1648 			SdrObjListIter aIterator(*pRenderedCustomShape);
1649 			while(aIterator.IsMore())
1650 			{
1651 				SdrObject* pCandidate = aIterator.Next();
1652 				SdrObjTransformInfoRec aInfo;
1653 				pCandidate->TakeObjInfo(aInfo);
1654 
1655 				// set path and poly conversion if one is possible since
1656 				// this object will first be broken
1657 				const sal_Bool bCanConvToPathOrPoly(aInfo.bCanConvToPath || aInfo.bCanConvToPoly);
1658 				if(rInfo.bCanConvToPath != bCanConvToPathOrPoly)
1659 				{
1660 					rInfo.bCanConvToPath = bCanConvToPathOrPoly;
1661 				}
1662 
1663 				if(rInfo.bCanConvToPoly != bCanConvToPathOrPoly)
1664 				{
1665 					rInfo.bCanConvToPoly = bCanConvToPathOrPoly;
1666 				}
1667 
1668 				if(rInfo.bCanConvToContour != aInfo.bCanConvToContour)
1669 				{
1670 					rInfo.bCanConvToContour = aInfo.bCanConvToContour;
1671 				}
1672 			}
1673 		}
1674 	}
1675 }
1676 
1677 void SdrObjCustomShape::SetModel(SdrModel* pNewModel)
1678 {
1679 	SdrTextObj::SetModel(pNewModel);
1680 	mXRenderedCustomShape.clear();
1681 }
1682 
1683 sal_uInt16 SdrObjCustomShape::GetObjIdentifier() const
1684 {
1685 	return sal_uInt16(OBJ_CUSTOMSHAPE);
1686 }
1687 
1688 ////////////////////////////////////////////////////////////////////////////////////////////////////
1689 ////////////////////////////////////////////////////////////////////////////////////////////////////
1690 ////////////////////////////////////////////////////////////////////////////////////////////////////
1691 
1692 void SdrObjCustomShape::RecalcSnapRect()
1693 {
1694 	SdrTextObj::RecalcSnapRect();
1695 }
1696 const Rectangle& SdrObjCustomShape::GetSnapRect() const
1697 {
1698 	return SdrTextObj::GetSnapRect();
1699 }
1700 const Rectangle& SdrObjCustomShape::GetCurrentBoundRect() const
1701 {
1702 	return SdrTextObj::GetCurrentBoundRect();
1703 }
1704 const Rectangle& SdrObjCustomShape::GetLogicRect() const
1705 {
1706 	return SdrTextObj::GetLogicRect();
1707 }
1708 void SdrObjCustomShape::NbcSetSnapRect( const Rectangle& rRect )
1709 {
1710 	aRect=rRect;
1711 	ImpJustifyRect(aRect);
1712 	InvalidateRenderGeometry();
1713 	Rectangle aTextBound( aRect );
1714 	if ( GetTextBounds( aTextBound ) )
1715 	{
1716 		if ( pModel==NULL || !pModel->IsPasteResize() )
1717 		{
1718 			long nHDist=GetTextLeftDistance()+GetTextRightDistance();
1719 			long nVDist=GetTextUpperDistance()+GetTextLowerDistance();
1720 			long nTWdt=aTextBound.GetWidth ()-1-nHDist; if (nTWdt<0) nTWdt=0;
1721 			long nTHgt=aTextBound.GetHeight()-1-nVDist; if (nTHgt<0) nTHgt=0;
1722 			if ( IsAutoGrowWidth() )
1723 				NbcSetMinTextFrameWidth( nTWdt );
1724 			if ( IsAutoGrowHeight() )
1725 				NbcSetMinTextFrameHeight( nTHgt );
1726 			NbcAdjustTextFrameWidthAndHeight();
1727 		}
1728 	}
1729 	ImpCheckShear();
1730 	SetRectsDirty();
1731 	SetChanged();
1732 }
1733 void SdrObjCustomShape::SetSnapRect( const Rectangle& rRect )
1734 {
1735 	Rectangle aBoundRect0;
1736 	if ( pUserCall )
1737 		aBoundRect0 = GetLastBoundRect();
1738 	NbcSetSnapRect( rRect );
1739 	BroadcastObjectChange();
1740 	SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
1741 }
1742 void SdrObjCustomShape::NbcSetLogicRect( const Rectangle& rRect )
1743 {
1744 	aRect = rRect;
1745 	ImpJustifyRect( aRect );
1746 	InvalidateRenderGeometry();
1747 	Rectangle aTextBound( aRect );
1748 	if ( GetTextBounds( aTextBound ) )
1749 	{
1750 		long nHDist=GetTextLeftDistance()+GetTextRightDistance();
1751 		long nVDist=GetTextUpperDistance()+GetTextLowerDistance();
1752 
1753 		long nTWdt=aTextBound.GetWidth()-1-nHDist; if (nTWdt<0) nTWdt=0;
1754 		long nTHgt=aTextBound.GetHeight()-1-nVDist; if (nTHgt<0) nTHgt=0;
1755 		if ( IsAutoGrowWidth() )
1756 			NbcSetMinTextFrameWidth( nTWdt );
1757 		if ( IsAutoGrowHeight() )
1758 			NbcSetMinTextFrameHeight( nTHgt );
1759 		NbcAdjustTextFrameWidthAndHeight();
1760 	}
1761 	SetRectsDirty();
1762 	SetChanged();
1763 }
1764 void SdrObjCustomShape::SetLogicRect( const Rectangle& rRect )
1765 {
1766 	Rectangle aBoundRect0;
1767 	if ( pUserCall )
1768 		aBoundRect0 = GetLastBoundRect();
1769 	NbcSetLogicRect(rRect);
1770 	BroadcastObjectChange();
1771 	SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
1772 }
1773 void SdrObjCustomShape::Move( const Size& rSiz )
1774 {
1775 	if ( rSiz.Width() || rSiz.Height() )
1776 	{
1777 		Rectangle aBoundRect0;
1778 		if ( pUserCall )
1779 			aBoundRect0 = GetLastBoundRect();
1780 		// #110094#-14 SendRepaintBroadcast();
1781 		NbcMove(rSiz);
1782 		SetChanged();
1783 		BroadcastObjectChange();
1784 		SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0);
1785 	}
1786 }
1787 void SdrObjCustomShape::NbcMove( const Size& rSiz )
1788 {
1789 	SdrTextObj::NbcMove( rSiz );
1790 	if ( mXRenderedCustomShape.is() )
1791 	{
1792 		SdrObject* pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape );
1793 		if ( pRenderedCustomShape )
1794         {
1795             // #i97149# the visualisation shape needs to be informed
1796             // about change, too
1797             pRenderedCustomShape->ActionChanged();
1798 			pRenderedCustomShape->NbcMove( rSiz );
1799         }
1800 	}
1801 
1802 	// #i37011# adapt geometry shadow
1803 	if(mpLastShadowGeometry)
1804 	{
1805 		mpLastShadowGeometry->NbcMove( rSiz );
1806 	}
1807 }
1808 void SdrObjCustomShape::Resize( const Point& rRef, const Fraction& xFact, const Fraction& yFact )
1809 {
1810 	SdrTextObj::Resize( rRef, xFact, yFact );
1811 }
1812 
1813 void SdrObjCustomShape::NbcResize( const Point& rRef, const Fraction& rxFact, const Fraction& ryFact )
1814 {
1815 	Fraction xFact( rxFact );
1816 	Fraction yFact( ryFact );
1817 
1818 	// taking care of handles that should not been changed
1819 	Rectangle aOld( aRect );
1820 	std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
1821 
1822 	SdrTextObj::NbcResize( rRef, xFact, yFact );
1823 
1824 	if ( ( xFact.GetNumerator() != xFact.GetDenominator() )
1825 		|| ( yFact.GetNumerator()!= yFact.GetDenominator() ) )
1826 	{
1827 		if ( ( ( xFact.GetNumerator() < 0 ) && ( xFact.GetDenominator() > 0 ) ) ||
1828 			( ( xFact.GetNumerator() > 0 ) && ( xFact.GetDenominator() < 0 ) ) )
1829 		{
1830 			SetMirroredX( IsMirroredX() == sal_False );
1831 		}
1832 		if ( ( ( yFact.GetNumerator() < 0 ) && ( yFact.GetDenominator() > 0 ) ) ||
1833 			( ( yFact.GetNumerator() > 0 ) && ( yFact.GetDenominator() < 0 ) ) )
1834 		{
1835 			SetMirroredY( IsMirroredY() == sal_False );
1836 		}
1837 	}
1838 
1839 	std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() );
1840 	while ( aIter != aInteractionHandles.end() )
1841 	{
1842 		try
1843 		{
1844 			if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
1845 				aIter->xInteraction->setControllerPosition( aIter->aPosition );
1846 			if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X )
1847 			{
1848 				sal_Int32 nX = ( aIter->aPosition.X - aOld.Left() ) + aRect.Left();
1849 				aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( nX, aIter->xInteraction->getPosition().Y ) );
1850 			}
1851 			if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y )
1852 			{
1853 				sal_Int32 nY = ( aIter->aPosition.Y - aOld.Top() ) + aRect.Top();
1854 				aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( aIter->xInteraction->getPosition().X, nY ) );
1855 			}
1856 		}
1857 		catch ( const uno::RuntimeException& )
1858 		{
1859 		}
1860 		aIter++;
1861 	}
1862 	InvalidateRenderGeometry();
1863 }
1864 void SdrObjCustomShape::NbcRotate( const Point& rRef, long nWink, double sn, double cs )
1865 {
1866 	sal_Bool bMirroredX = IsMirroredX();
1867 	sal_Bool bMirroredY = IsMirroredY();
1868 
1869 	fObjectRotation = fmod( fObjectRotation, 360.0 );
1870 	if ( fObjectRotation < 0 )
1871 		fObjectRotation = 360 + fObjectRotation;
1872 
1873 	// the rotation angle for ashapes is stored in fObjectRotation, this rotation
1874 	// has to be applied to the text object (which is internally using aGeo.nWink).
1875 	SdrTextObj::NbcRotate( aRect.TopLeft(), -aGeo.nDrehWink,		// retrieving the unrotated text object
1876 							sin( (-aGeo.nDrehWink) * F_PI18000 ),
1877 							cos( (-aGeo.nDrehWink) * F_PI18000 ) );
1878 	aGeo.nDrehWink = 0;												// resetting aGeo data
1879 	aGeo.RecalcSinCos();
1880 
1881 	long nW = (long)( fObjectRotation * 100 );						// applying our object rotation
1882 	if ( bMirroredX )
1883 		nW = 36000 - nW;
1884 	if ( bMirroredY )
1885 		nW = 18000 - nW;
1886 	nW = nW % 36000;
1887 	if ( nW < 0 )
1888 		nW = 36000 + nW;
1889 	SdrTextObj::NbcRotate( aRect.TopLeft(), nW,						// applying text rotation
1890 							sin( nW * F_PI18000 ),
1891 							cos( nW * F_PI18000 ) );
1892 
1893 	int nSwap = 0;
1894 	if ( bMirroredX )
1895 		nSwap ^= 1;
1896 	if ( bMirroredY )
1897 		nSwap ^= 1;
1898 
1899 	double fWink = nWink;													// updating to our new object rotation
1900 	fWink /= 100.0;
1901 	fObjectRotation = fmod( nSwap ? fObjectRotation - fWink : fObjectRotation + fWink, 360.0 );
1902 	if ( fObjectRotation < 0 )
1903 		fObjectRotation = 360 + fObjectRotation;
1904 
1905 	SdrTextObj::NbcRotate( rRef, nWink, sn, cs );							// applying text rotation
1906 	InvalidateRenderGeometry();
1907 }
1908 
1909 void SdrObjCustomShape::NbcMirror( const Point& rRef1, const Point& rRef2 )
1910 {
1911 	// storing horizontal and vertical flipping without modifying the rotate angle
1912 
1913 	sal_Bool bHorz = sal_False;
1914 	sal_Bool bVert = sal_False;
1915 	if ( rRef1.X() == rRef2.X() )
1916 		bHorz = sal_True;
1917 	if ( rRef1.Y() == rRef2.Y() )
1918 		bVert = sal_True;
1919 	if ( !bHorz && !bVert )
1920 		bHorz = bVert = sal_True;
1921 
1922 	if ( bHorz || bVert )
1923 	{
1924 		SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
1925 
1926 		/////////////////
1927 		// "MirroredX" //
1928 		/////////////////
1929 		if ( bHorz )
1930 		{
1931 			const rtl::OUString	sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) );
1932 			com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX );
1933 			if ( pAny )
1934 			{
1935 				sal_Bool bFlip = sal_Bool();
1936 				if ( *pAny >>= bFlip )
1937 				{
1938 					if ( bFlip )
1939 						bHorz = sal_False;
1940 				}
1941 			}
1942 			PropertyValue aPropVal;
1943 			aPropVal.Name = sMirroredX;
1944 			aPropVal.Value <<= bHorz;
1945 			aGeometryItem.SetPropertyValue( aPropVal );
1946 		}
1947 
1948 		/////////////////
1949 		// "MirroredY" //
1950 		/////////////////
1951 		if ( bVert )
1952 		{
1953 			const rtl::OUString	sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) );
1954 			com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY );
1955 			if ( pAny )
1956 			{
1957 				sal_Bool bFlip = sal_Bool();
1958 				if ( *pAny >>= bFlip )
1959 				{
1960 					if ( bFlip )
1961 						bVert = sal_False;
1962 				}
1963 			}
1964 			PropertyValue aPropVal;
1965 			aPropVal.Name = sMirroredY;
1966 			aPropVal.Value <<= bVert;
1967 			aGeometryItem.SetPropertyValue( aPropVal );
1968 		}
1969 		SetMergedItem( aGeometryItem );
1970 	}
1971 	SdrTextObj::NbcMirror( rRef1, rRef2 );
1972 	InvalidateRenderGeometry();
1973 }
1974 
1975 void SdrObjCustomShape::Shear( const Point& rRef, long nWink, double tn, FASTBOOL bVShear )
1976 {
1977 	SdrTextObj::Shear( rRef, nWink, tn, bVShear );
1978 	InvalidateRenderGeometry();
1979 }
1980 void SdrObjCustomShape::NbcShear( const Point& rRef, long nWink, double tn, FASTBOOL bVShear )
1981 {
1982 	long nDrehWink = aGeo.nDrehWink;
1983 	if ( nDrehWink )
1984 	{
1985 		aGeo.nDrehWink = -nDrehWink;
1986 		aGeo.RecalcSinCos();
1987 		NbcRotate( rRef, aGeo.nDrehWink, aGeo.nSin, aGeo.nCos );
1988 	}
1989 	SdrTextObj::NbcShear(rRef,nWink,tn,bVShear);
1990 	if ( nDrehWink )
1991 	{
1992 		aGeo.nDrehWink = nDrehWink;
1993 		aGeo.RecalcSinCos();
1994 		Rotate( rRef, aGeo.nDrehWink, aGeo.nSin, aGeo.nCos );
1995 	}
1996 	InvalidateRenderGeometry();
1997 }
1998 
1999 ////////////////////////////////////////////////////////////////////////////////////////////////////
2000 
2001 SdrGluePoint SdrObjCustomShape::GetVertexGluePoint(sal_uInt16 nPosNum) const
2002 {
2003 	sal_Int32 nWdt = ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue();
2004 
2005 	// #i25616#
2006 	if(!LineIsOutsideGeometry())
2007 	{
2008 		nWdt++;
2009 		nWdt /= 2;
2010 	}
2011 
2012 	Point aPt;
2013 	switch (nPosNum) {
2014 		case 0: aPt=aRect.TopCenter();    aPt.Y()-=nWdt; break;
2015 		case 1: aPt=aRect.RightCenter();  aPt.X()+=nWdt; break;
2016 		case 2: aPt=aRect.BottomCenter(); aPt.Y()+=nWdt; break;
2017 		case 3: aPt=aRect.LeftCenter();   aPt.X()-=nWdt; break;
2018 	}
2019 	if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan);
2020 	if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
2021 	aPt-=GetSnapRect().Center();
2022 	SdrGluePoint aGP(aPt);
2023 	aGP.SetPercent(sal_False);
2024 	return aGP;
2025 }
2026 
2027 ////////////////////////////////////////////////////////////////////////////////////////////////////
2028 
2029 // #i38892#
2030 void SdrObjCustomShape::ImpCheckCustomGluePointsAreAdded()
2031 {
2032 	const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
2033 
2034 	if(pSdrObject)
2035 	{
2036 		const SdrGluePointList* pSource = pSdrObject->GetGluePointList();
2037 
2038 		if(pSource && pSource->GetCount())
2039 		{
2040 			if(!SdrTextObj::GetGluePointList())
2041 			{
2042 				SdrTextObj::ForceGluePointList();
2043 			}
2044 
2045 			const SdrGluePointList* pList = SdrTextObj::GetGluePointList();
2046 
2047 			if(pList)
2048 			{
2049 				SdrGluePointList aNewList;
2050 				sal_uInt16 a;
2051 
2052 				for(a = 0; a < pSource->GetCount(); a++)
2053 				{
2054 					SdrGluePoint aCopy((*pSource)[a]);
2055 					aCopy.SetUserDefined(sal_False);
2056 					aNewList.Insert(aCopy);
2057 				}
2058 
2059 				sal_Bool bMirroredX = IsMirroredX();
2060 				sal_Bool bMirroredY = IsMirroredY();
2061 
2062 				long nShearWink = aGeo.nShearWink;
2063 				double fTan = aGeo.nTan;
2064 
2065 				if ( aGeo.nDrehWink || nShearWink || bMirroredX || bMirroredY )
2066 				{
2067 					Polygon aPoly( aRect );
2068 					if( nShearWink )
2069 					{
2070 						sal_uInt16 nPointCount=aPoly.GetSize();
2071 						for (sal_uInt16 i=0; i<nPointCount; i++)
2072 							ShearPoint(aPoly[i],aRect.Center(), fTan, sal_False );
2073 					}
2074 					if ( aGeo.nDrehWink )
2075 						aPoly.Rotate( aRect.Center(), aGeo.nDrehWink / 10 );
2076 
2077 					Rectangle aBoundRect( aPoly.GetBoundRect() );
2078 					sal_Int32 nXDiff = aBoundRect.Left() - aRect.Left();
2079 					sal_Int32 nYDiff = aBoundRect.Top() - aRect.Top();
2080 
2081 					if (nShearWink&&((bMirroredX&&!bMirroredY)||(bMirroredY&&!bMirroredX)))
2082 					{
2083 						nShearWink = -nShearWink;
2084 						fTan = -fTan;
2085 					}
2086 
2087 					Point aRef( aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
2088 					for ( a = 0; a < aNewList.GetCount(); a++ )
2089 					{
2090 						SdrGluePoint& rPoint = aNewList[ a ];
2091 						Point aGlue( rPoint.GetPos() );
2092 						if ( nShearWink )
2093 							ShearPoint( aGlue, aRef, fTan );
2094 
2095 						RotatePoint( aGlue, aRef, sin( fObjectRotation * F_PI180 ), cos( fObjectRotation * F_PI180 ) );
2096 						if ( bMirroredX )
2097 							aGlue.X() = aRect.GetWidth() - aGlue.X();
2098 						if ( bMirroredY )
2099 							aGlue.Y() = aRect.GetHeight() - aGlue.Y();
2100 						aGlue.X() -= nXDiff;
2101 						aGlue.Y() -= nYDiff;
2102 						rPoint.SetPos( aGlue );
2103 					}
2104 				}
2105 
2106 				for(a = 0; a < pList->GetCount(); a++)
2107 				{
2108 					const SdrGluePoint& rCandidate = (*pList)[a];
2109 
2110 					if(rCandidate.IsUserDefined())
2111 					{
2112 						aNewList.Insert(rCandidate);
2113 					}
2114 				}
2115 
2116 				// copy new list to local. This is NOT very convenient behaviour, the local
2117 				// GluePointList should not be set, but be delivered by using GetGluePointList(),
2118 				// maybe on demand. Since the local object is changed here, this is assumed to
2119 				// be a result of GetGluePointList and thus the list is copied
2120 				if(pPlusData)
2121 				{
2122 					*pPlusData->pGluePoints = aNewList;
2123 				}
2124 			}
2125 		}
2126 	}
2127 }
2128 
2129 // #i38892#
2130 const SdrGluePointList* SdrObjCustomShape::GetGluePointList() const
2131 {
2132 	((SdrObjCustomShape*)this)->ImpCheckCustomGluePointsAreAdded();
2133 	return SdrTextObj::GetGluePointList();
2134 }
2135 
2136 // #i38892#
2137 //SdrGluePointList* SdrObjCustomShape::GetGluePointList()
2138 //{
2139 //	ImpCheckCustomGluePointsAreAdded();
2140 //	return SdrTextObj::GetGluePointList();
2141 //}
2142 
2143 // #i38892#
2144 SdrGluePointList* SdrObjCustomShape::ForceGluePointList()
2145 {
2146 	if(SdrTextObj::ForceGluePointList())
2147 	{
2148 		ImpCheckCustomGluePointsAreAdded();
2149 		return SdrTextObj::ForceGluePointList();
2150 	}
2151 	else
2152 	{
2153 		return 0L;
2154 	}
2155 }
2156 
2157 ////////////////////////////////////////////////////////////////////////////////////////////////////
2158 ////////////////////////////////////////////////////////////////////////////////////////////////////
2159 ////////////////////////////////////////////////////////////////////////////////////////////////////
2160 
2161 sal_uInt32 SdrObjCustomShape::GetHdlCount() const
2162 {
2163 	const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount());
2164 	std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
2165 	return ( aInteractionHandles.size() + nBasicHdlCount );
2166 }
2167 
2168 SdrHdl* SdrObjCustomShape::GetHdl( sal_uInt32 nHdlNum ) const
2169 {
2170 	SdrHdl* pH = NULL;
2171 	const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount());
2172 
2173 	if ( nHdlNum < nBasicHdlCount )
2174 		pH = SdrTextObj::GetHdl( nHdlNum );
2175 	else
2176 	{
2177 		std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
2178 		const sal_uInt32 nCustomShapeHdlNum(nHdlNum - nBasicHdlCount);
2179 
2180 		if ( nCustomShapeHdlNum < aInteractionHandles.size() )
2181 		{
2182 			if ( aInteractionHandles[ nCustomShapeHdlNum ].xInteraction.is() )
2183 			{
2184 				try
2185 				{
2186 					com::sun::star::awt::Point aPosition( aInteractionHandles[ nCustomShapeHdlNum ].xInteraction->getPosition() );
2187 					pH = new SdrHdl( Point( aPosition.X, aPosition.Y ), HDL_CUSTOMSHAPE1 );
2188 					pH->SetPointNum( nCustomShapeHdlNum );
2189 					pH->SetObj( (SdrObject*)this );
2190 				}
2191 				catch ( const uno::RuntimeException& )
2192 				{
2193 				}
2194 			}
2195 		}
2196 	}
2197 	return pH;
2198 }
2199 
2200 ////////////////////////////////////////////////////////////////////////////////////////////////////
2201 
2202 bool SdrObjCustomShape::hasSpecialDrag() const
2203 {
2204 	return true;
2205 }
2206 
2207 bool SdrObjCustomShape::beginSpecialDrag(SdrDragStat& rDrag) const
2208 {
2209 	const SdrHdl* pHdl = rDrag.GetHdl();
2210 
2211     if(pHdl && HDL_CUSTOMSHAPE1 == pHdl->GetKind())
2212 	{
2213 		rDrag.SetEndDragChangesAttributes(true);
2214 		rDrag.SetNoSnap(true);
2215 	}
2216 	else
2217 	{
2218 		const SdrHdl* pHdl2 = rDrag.GetHdl();
2219 		const SdrHdlKind eHdl((pHdl2 == NULL) ? HDL_MOVE : pHdl2->GetKind());
2220 
2221         switch( eHdl )
2222 		{
2223 			case HDL_UPLFT :
2224 			case HDL_UPPER :
2225 			case HDL_UPRGT :
2226 			case HDL_LEFT  :
2227 			case HDL_RIGHT :
2228 			case HDL_LWLFT :
2229 			case HDL_LOWER :
2230 			case HDL_LWRGT :
2231 			case HDL_MOVE  :
2232 			{
2233     			break;
2234 			}
2235 			default:
2236             {
2237 				return false;
2238             }
2239 		}
2240 	}
2241 
2242     return true;
2243 }
2244 
2245 void SdrObjCustomShape::DragResizeCustomShape( const Rectangle& rNewRect, SdrObjCustomShape* pObj ) const
2246 {
2247 	Rectangle	aOld( pObj->aRect );
2248 	sal_Bool	bOldMirroredX( pObj->IsMirroredX() );
2249 	sal_Bool	bOldMirroredY( pObj->IsMirroredY() );
2250 
2251 	Rectangle aNewRect( rNewRect );
2252 	aNewRect.Justify();
2253 
2254 	std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( pObj ) );
2255 
2256 	GeoStat aGeoStat( pObj->GetGeoStat() );
2257 	if ( aNewRect.TopLeft()!= pObj->aRect.TopLeft() &&
2258 		( pObj->aGeo.nDrehWink || pObj->aGeo.nShearWink ) )
2259 	{
2260 		Point aNewPos( aNewRect.TopLeft() );
2261 		if ( pObj->aGeo.nShearWink ) ShearPoint( aNewPos, aOld.TopLeft(), aGeoStat.nTan );
2262 		if ( pObj->aGeo.nDrehWink )  RotatePoint(aNewPos, aOld.TopLeft(), aGeoStat.nSin, aGeoStat.nCos );
2263 		aNewRect.SetPos( aNewPos );
2264 	}
2265 	if ( aNewRect != pObj->aRect )
2266 	{
2267 		pObj->SetLogicRect( aNewRect );
2268 		pObj->InvalidateRenderGeometry();
2269 
2270 		if ( rNewRect.Left() > rNewRect.Right() )
2271 		{
2272 			Point aTop( ( pObj->GetSnapRect().Left() + pObj->GetSnapRect().Right() ) >> 1, pObj->GetSnapRect().Top() );
2273 			Point aBottom( aTop.X(), aTop.Y() + 1000 );
2274 			pObj->NbcMirror( aTop, aBottom );
2275 		}
2276 		if ( rNewRect.Top() > rNewRect.Bottom() )
2277 		{
2278 			Point aLeft( pObj->GetSnapRect().Left(), ( pObj->GetSnapRect().Top() + pObj->GetSnapRect().Bottom() ) >> 1 );
2279 			Point aRight( aLeft.X() + 1000, aLeft.Y() );
2280 			pObj->NbcMirror( aLeft, aRight );
2281 		}
2282 
2283 		std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() );
2284 		while ( aIter != aInteractionHandles.end() )
2285 		{
2286 			try
2287 			{
2288 				if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2289 					aIter->xInteraction->setControllerPosition( aIter->aPosition );
2290 				if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X )
2291 				{
2292 					sal_Int32 nX;
2293 					if ( bOldMirroredX )
2294 					{
2295 						nX = ( aIter->aPosition.X - aOld.Right() );
2296 						if ( rNewRect.Left() > rNewRect.Right() )
2297 							nX = pObj->aRect.Left() - nX;
2298 						else
2299 							nX += pObj->aRect.Right();
2300 					}
2301 					else
2302 					{
2303 						nX = ( aIter->aPosition.X - aOld.Left() );
2304 						if ( rNewRect.Left() > rNewRect.Right() )
2305 							nX = pObj->aRect.Right() - nX;
2306 						else
2307 							nX += pObj->aRect.Left();
2308 					}
2309 					aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( nX, aIter->xInteraction->getPosition().Y ) );
2310 				}
2311 				if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y )
2312 				{
2313 					sal_Int32 nY;
2314 					if ( bOldMirroredY )
2315 					{
2316 						nY = ( aIter->aPosition.Y - aOld.Bottom() );
2317 						if ( rNewRect.Top() > rNewRect.Bottom() )
2318 							nY = pObj->aRect.Top() - nY;
2319 						else
2320 							nY += pObj->aRect.Bottom();
2321 					}
2322 					else
2323 					{
2324 						nY = ( aIter->aPosition.Y - aOld.Top() );
2325 						if ( rNewRect.Top() > rNewRect.Bottom() )
2326 							nY = pObj->aRect.Bottom() - nY;
2327 						else
2328 							nY += pObj->aRect.Top();
2329 					}
2330 					aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( aIter->xInteraction->getPosition().X, nY ) );
2331 				}
2332 			}
2333 			catch ( const uno::RuntimeException& )
2334 			{
2335 			}
2336 			aIter++;
2337 		}
2338 	}
2339 }
2340 
2341 void SdrObjCustomShape::DragMoveCustomShapeHdl( const Point aDestination, const sal_uInt16 nCustomShapeHdlNum, SdrObjCustomShape* pObj ) const
2342 {
2343 	std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( pObj ) );
2344 	if ( nCustomShapeHdlNum < aInteractionHandles.size() )
2345 	{
2346 		SdrCustomShapeInteraction aInteractionHandle( aInteractionHandles[ nCustomShapeHdlNum ] );
2347 		if ( aInteractionHandle.xInteraction.is() )
2348 		{
2349 			try
2350 			{
2351 				com::sun::star::awt::Point aPt( aDestination.X(), aDestination.Y() );
2352 				if ( aInteractionHandle.nMode & CUSTOMSHAPE_HANDLE_MOVE_SHAPE )
2353 				{
2354 					sal_Int32 nXDiff = aPt.X - aInteractionHandle.aPosition.X;
2355 					sal_Int32 nYDiff = aPt.Y - aInteractionHandle.aPosition.Y;
2356 
2357 					pObj->aRect.Move( nXDiff, nYDiff );
2358 					pObj->aOutRect.Move( nXDiff, nYDiff );
2359 					pObj->maSnapRect.Move( nXDiff, nYDiff );
2360 					pObj->SetRectsDirty(sal_True);
2361 					pObj->InvalidateRenderGeometry();
2362 
2363 					std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() );
2364 					while ( aIter != aInteractionHandles.end() )
2365 					{
2366 						if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2367 						{
2368 							if ( aIter->xInteraction.is() )
2369 								aIter->xInteraction->setControllerPosition( aIter->aPosition );
2370 						}
2371 						aIter++;
2372 					}
2373 				}
2374 				aInteractionHandle.xInteraction->setControllerPosition( aPt );
2375 			}
2376 			catch ( const uno::RuntimeException& )
2377 			{
2378 			}
2379 		}
2380 	}
2381 }
2382 
2383 bool SdrObjCustomShape::applySpecialDrag(SdrDragStat& rDrag)
2384 {
2385 	const SdrHdl* pHdl = rDrag.GetHdl();
2386 	const SdrHdlKind eHdl((pHdl == NULL) ? HDL_MOVE : pHdl->GetKind());
2387 
2388     switch(eHdl)
2389 	{
2390 		case HDL_CUSTOMSHAPE1 :
2391 		{
2392 			rDrag.SetEndDragChangesGeoAndAttributes(true);
2393 		    DragMoveCustomShapeHdl( rDrag.GetNow(), (sal_uInt16)pHdl->GetPointNum(), this );
2394 		    SetRectsDirty();
2395 		    InvalidateRenderGeometry();
2396 		    SetChanged();
2397             break;
2398 		}
2399 
2400 		case HDL_UPLFT :
2401 		case HDL_UPPER :
2402 		case HDL_UPRGT :
2403 		case HDL_LEFT  :
2404 		case HDL_RIGHT :
2405 		case HDL_LWLFT :
2406 		case HDL_LOWER :
2407 		case HDL_LWRGT :
2408 		{
2409 			DragResizeCustomShape(ImpDragCalcRect(rDrag), this);
2410 			break;
2411 		}
2412 		case HDL_MOVE :
2413 		{
2414 			Move(Size(rDrag.GetDX(), rDrag.GetDY()));
2415 			break;
2416 		}
2417 		default: break;
2418 	}
2419 
2420     return true;
2421 }
2422 
2423 ////////////////////////////////////////////////////////////////////////////////////////////////////
2424 
2425 void SdrObjCustomShape::DragCreateObject( SdrDragStat& rStat )
2426 {
2427 	Rectangle aRect1;
2428 	rStat.TakeCreateRect( aRect1 );
2429 
2430 	std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
2431 
2432 	sal_uInt32 nDefaultObjectSizeWidth = 3000;		// default width from SDOptions ?
2433 	sal_uInt32 nDefaultObjectSizeHeight= 3000;
2434 
2435 	if ( ImpVerticalSwitch( *this ) )
2436 	{
2437 		SetMirroredX( aRect1.Left() > aRect1.Right() );
2438 
2439 		aRect1 = Rectangle( rStat.GetNow(), Size( nDefaultObjectSizeWidth, nDefaultObjectSizeHeight ) );
2440 		// subtracting the horizontal difference of the latest handle from shape position
2441 		if ( !aInteractionHandles.empty() )
2442 		{
2443 			sal_Int32 nHandlePos = aInteractionHandles[ aInteractionHandles.size() - 1 ].xInteraction->getPosition().X;
2444 			aRect1.Move( aRect.Left() - nHandlePos, 0 );
2445 		}
2446 	}
2447 	ImpJustifyRect( aRect1 );
2448 	rStat.SetActionRect( aRect1 );
2449 	aRect = aRect1;
2450 	SetRectsDirty();
2451 
2452 	std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() );
2453 	while ( aIter != aInteractionHandles.end() )
2454 	{
2455 		try
2456 		{
2457 			if ( aIter->nMode & CUSTOMSHAPE_HANDLE_CREATE_FIXED )
2458 				aIter->xInteraction->setControllerPosition( awt::Point( rStat.GetStart().X(), rStat.GetStart().Y() ) );
2459 		}
2460 		catch ( const uno::RuntimeException& )
2461 		{
2462 		}
2463 		aIter++;
2464 	}
2465 
2466 	SetBoundRectDirty();
2467 	bSnapRectDirty=sal_True;
2468 }
2469 
2470 FASTBOOL SdrObjCustomShape::BegCreate( SdrDragStat& rDrag )
2471 {
2472 	return SdrTextObj::BegCreate( rDrag );
2473 }
2474 
2475 FASTBOOL SdrObjCustomShape::MovCreate(SdrDragStat& rStat)
2476 {
2477 	SdrView* pView = rStat.GetView();		// #i37448#
2478 	if( pView && pView->IsSolidDragging() )
2479 	{
2480 		InvalidateRenderGeometry();
2481 	}
2482 	DragCreateObject( rStat );
2483 	SetRectsDirty();
2484 	return sal_True;
2485 }
2486 
2487 FASTBOOL SdrObjCustomShape::EndCreate( SdrDragStat& rStat, SdrCreateCmd eCmd )
2488 {
2489 	DragCreateObject( rStat );
2490 
2491 	if ( bTextFrame )
2492 	{
2493 		if ( IsAutoGrowHeight() )
2494 		{
2495 			// MinTextHeight
2496 			long nHgt=aRect.GetHeight()-1;
2497 			if (nHgt==1) nHgt=0;
2498 			NbcSetMinTextFrameHeight( nHgt );
2499 		}
2500 		if ( IsAutoGrowWidth() )
2501 		{
2502 			// MinTextWidth
2503 			long nWdt=aRect.GetWidth()-1;
2504 			if (nWdt==1) nWdt=0;
2505 			NbcSetMinTextFrameWidth( nWdt );
2506 		}
2507 		// Textrahmen neu berechnen
2508 		NbcAdjustTextFrameWidthAndHeight();
2509 	}
2510 	SetRectsDirty();
2511 	return ( eCmd == SDRCREATE_FORCEEND || rStat.GetPointAnz() >= 2 );
2512 }
2513 
2514 basegfx::B2DPolyPolygon SdrObjCustomShape::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
2515 {
2516 	return GetLineGeometry( this, sal_False );
2517 }
2518 
2519 ////////////////////////////////////////////////////////////////////////////////////////////////////
2520 ////////////////////////////////////////////////////////////////////////////////////////////////////
2521 ////////////////////////////////////////////////////////////////////////////////////////////////////
2522 
2523 // in context with the SdrObjCustomShape the SdrTextAutoGrowHeightItem == true -> Resize Shape to fit text,
2524 //									   the SdrTextAutoGrowWidthItem  == true -> Word wrap text in Shape
2525 FASTBOOL SdrObjCustomShape::IsAutoGrowHeight() const
2526 {
2527 	const SfxItemSet& rSet = GetMergedItemSet();
2528 	FASTBOOL bIsAutoGrowHeight = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
2529 	if ( bIsAutoGrowHeight && IsVerticalWriting() )
2530 		bIsAutoGrowHeight = ((SdrTextWordWrapItem&)(rSet.Get(SDRATTR_TEXT_WORDWRAP))).GetValue() == sal_False;
2531 	return bIsAutoGrowHeight;
2532 }
2533 FASTBOOL SdrObjCustomShape::IsAutoGrowWidth() const
2534 {
2535 	const SfxItemSet& rSet = GetMergedItemSet();
2536 	FASTBOOL bIsAutoGrowWidth = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
2537 	if ( bIsAutoGrowWidth && !IsVerticalWriting() )
2538 		bIsAutoGrowWidth = ((SdrTextWordWrapItem&)(rSet.Get(SDRATTR_TEXT_WORDWRAP))).GetValue() == sal_False;
2539 	return bIsAutoGrowWidth;
2540 }
2541 
2542 /* The following method is identical to the SdrTextObj::SetVerticalWriting method, the only difference
2543    is that the SdrAutoGrowWidthItem and SdrAutoGrowHeightItem are not exchanged if the vertical writing
2544    mode has been changed */
2545 
2546 void SdrObjCustomShape::SetVerticalWriting( sal_Bool bVertical )
2547 {
2548 	ForceOutlinerParaObject();
2549 
2550 	OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
2551 
2552 	DBG_ASSERT( pOutlinerParaObject, "SdrTextObj::SetVerticalWriting() without OutlinerParaObject!" );
2553 
2554 	if( pOutlinerParaObject )
2555 	{
2556 		if(pOutlinerParaObject->IsVertical() != (bool)bVertical)
2557 		{
2558 			// get item settings
2559 			const SfxItemSet& rSet = GetObjectItemSet();
2560 
2561 			// #103516# Also exchange hor/ver adjust items
2562 			SdrTextHorzAdjust eHorz = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue();
2563 			SdrTextVertAdjust eVert = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
2564 
2565 			// rescue object size
2566 			Rectangle aObjectRect = GetSnapRect();
2567 
2568 			// prepare ItemSet to set exchanged width and height items
2569 			SfxItemSet aNewSet(*rSet.GetPool(),
2570 				SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT,
2571 				// #103516# Expanded item ranges to also support hor and ver adjust.
2572 				SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST,
2573 				SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST,
2574 				0, 0);
2575 
2576 			aNewSet.Put(rSet);
2577 
2578 			// #103516# Exchange horz and vert adjusts
2579 			switch(eVert)
2580 			{
2581 				case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break;
2582 				case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break;
2583 				case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break;
2584 				case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break;
2585 			}
2586 			switch(eHorz)
2587 			{
2588 				case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break;
2589 				case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break;
2590 				case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break;
2591 				case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break;
2592 			}
2593 
2594 			SetObjectItemSet( aNewSet );
2595 			pOutlinerParaObject = GetOutlinerParaObject();
2596 			if ( pOutlinerParaObject )
2597 				pOutlinerParaObject->SetVertical(bVertical);
2598 
2599 			// restore object size
2600 			SetSnapRect(aObjectRect);
2601 		}
2602 	}
2603 }
2604 FASTBOOL SdrObjCustomShape::AdjustTextFrameWidthAndHeight(Rectangle& rR, FASTBOOL bHgt, FASTBOOL bWdt) const
2605 {
2606  	if ( pModel && HasText() && !rR.IsEmpty() )
2607 	{
2608 		FASTBOOL bWdtGrow=bWdt && IsAutoGrowWidth();
2609 		FASTBOOL bHgtGrow=bHgt && IsAutoGrowHeight();
2610 		if ( bWdtGrow || bHgtGrow )
2611 		{
2612 			Rectangle aR0(rR);
2613 			long nHgt=0,nMinHgt=0,nMaxHgt=0;
2614 			long nWdt=0,nMinWdt=0,nMaxWdt=0;
2615 			Size aSiz(rR.GetSize()); aSiz.Width()--; aSiz.Height()--;
2616 			Size aMaxSiz(100000,100000);
2617 			Size aTmpSiz(pModel->GetMaxObjSize());
2618 			if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width();
2619 			if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height();
2620 			if (bWdtGrow)
2621 			{
2622 				nMinWdt=GetMinTextFrameWidth();
2623 				nMaxWdt=GetMaxTextFrameWidth();
2624 				if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width();
2625 				if (nMinWdt<=0) nMinWdt=1;
2626 				aSiz.Width()=nMaxWdt;
2627 			}
2628 			if (bHgtGrow)
2629 			{
2630 				nMinHgt=GetMinTextFrameHeight();
2631 				nMaxHgt=GetMaxTextFrameHeight();
2632 				if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height();
2633 				if (nMinHgt<=0) nMinHgt=1;
2634 				aSiz.Height()=nMaxHgt;
2635 			}
2636 			long nHDist=GetTextLeftDistance()+GetTextRightDistance();
2637 			long nVDist=GetTextUpperDistance()+GetTextLowerDistance();
2638 			aSiz.Width()-=nHDist;
2639 			aSiz.Height()-=nVDist;
2640 			if ( aSiz.Width() < 2 )
2641 				aSiz.Width() = 2;   // Mindestgroesse 2
2642 			if ( aSiz.Height() < 2 )
2643 				aSiz.Height() = 2; // Mindestgroesse 2
2644 
2645 			if(pEdtOutl)
2646 			{
2647 				pEdtOutl->SetMaxAutoPaperSize( aSiz );
2648 				if (bWdtGrow)
2649 				{
2650 					Size aSiz2(pEdtOutl->CalcTextSize());
2651 					nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz
2652 					if (bHgtGrow) nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz
2653 				} else
2654 				{
2655 					nHgt=pEdtOutl->GetTextHeight()+1; // lieber etwas Tolleranz
2656 				}
2657 			}
2658 			else
2659 			{
2660 				Outliner& rOutliner=ImpGetDrawOutliner();
2661 				rOutliner.SetPaperSize(aSiz);
2662 				rOutliner.SetUpdateMode(sal_True);
2663 				// !!! hier sollte ich wohl auch noch mal die Optimierung mit
2664 				// bPortionInfoChecked usw einbauen
2665 				OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
2666 				if( pOutlinerParaObject != NULL )
2667 				{
2668 					rOutliner.SetText(*pOutlinerParaObject);
2669 					rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
2670 				}
2671 				if ( bWdtGrow )
2672 				{
2673 					Size aSiz2(rOutliner.CalcTextSize());
2674 					nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz
2675 					if ( bHgtGrow )
2676 						nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz
2677 				}
2678 				else
2679 					nHgt = rOutliner.GetTextHeight()+1; // lieber etwas Tolleranz
2680 				rOutliner.Clear();
2681 			}
2682 			if ( nWdt < nMinWdt )
2683 				nWdt = nMinWdt;
2684 			if ( nWdt > nMaxWdt )
2685 				nWdt = nMaxWdt;
2686 			nWdt += nHDist;
2687 			if ( nWdt < 1 )
2688 				nWdt = 1; // nHDist kann auch negativ sein
2689 			if ( nHgt < nMinHgt )
2690 				nHgt = nMinHgt;
2691 			if ( nHgt > nMaxHgt )
2692 				nHgt = nMaxHgt;
2693 			nHgt+=nVDist;
2694 			if ( nHgt < 1 )
2695 				nHgt = 1; // nVDist kann auch negativ sein
2696 			long nWdtGrow = nWdt-(rR.Right()-rR.Left());
2697 			long nHgtGrow = nHgt-(rR.Bottom()-rR.Top());
2698 			if ( nWdtGrow == 0 )
2699 				bWdtGrow = sal_False;
2700 			if ( nHgtGrow == 0 )
2701 				bHgtGrow=sal_False;
2702 			if ( bWdtGrow || bHgtGrow )
2703 			{
2704 				if ( bWdtGrow )
2705 				{
2706 					SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
2707 					if ( eHAdj == SDRTEXTHORZADJUST_LEFT )
2708 						rR.Right()+=nWdtGrow;
2709 					else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT )
2710 						rR.Left()-=nWdtGrow;
2711 					else
2712 					{
2713 						long nWdtGrow2=nWdtGrow/2;
2714 						rR.Left()-=nWdtGrow2;
2715 						rR.Right()=rR.Left()+nWdt;
2716 					}
2717 				}
2718 				if ( bHgtGrow )
2719 				{
2720 					SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
2721 					if ( eVAdj == SDRTEXTVERTADJUST_TOP )
2722 						rR.Bottom()+=nHgtGrow;
2723 					else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM )
2724 						rR.Top()-=nHgtGrow;
2725 					else
2726 					{
2727 						long nHgtGrow2=nHgtGrow/2;
2728 						rR.Top()-=nHgtGrow2;
2729 						rR.Bottom()=rR.Top()+nHgt;
2730 					}
2731 				}
2732 				if ( aGeo.nDrehWink )
2733 				{
2734 					Point aD1(rR.TopLeft());
2735 					aD1-=aR0.TopLeft();
2736 					Point aD2(aD1);
2737 					RotatePoint(aD2,Point(),aGeo.nSin,aGeo.nCos);
2738 					aD2-=aD1;
2739 					rR.Move(aD2.X(),aD2.Y());
2740 				}
2741 				return sal_True;
2742 			}
2743 		}
2744 	}
2745 	return sal_False;
2746 }
2747 
2748 Rectangle SdrObjCustomShape::ImpCalculateTextFrame( const FASTBOOL bHgt, const FASTBOOL bWdt )
2749 {
2750 	Rectangle aReturnValue;
2751 
2752 	Rectangle aOldTextRect( aRect );		// <- initial text rectangle
2753 
2754 	Rectangle aNewTextRect( aRect );		// <- new text rectangle returned from the custom shape renderer,
2755 	GetTextBounds( aNewTextRect );			//    it depends to the current logical shape size
2756 
2757 	Rectangle aAdjustedTextRect( aNewTextRect );							// <- new text rectangle is being tested by AdjustTextFrameWidthAndHeight to ensure
2758 	if ( AdjustTextFrameWidthAndHeight( aAdjustedTextRect, bHgt, bWdt ) )	//    that the new text rectangle is matching the current text size from the outliner
2759 	{
2760 		if ( ( aAdjustedTextRect != aNewTextRect ) && ( aOldTextRect != aAdjustedTextRect ) )
2761 		{
2762 			aReturnValue = aRect;
2763 			double fXScale = (double)aOldTextRect.GetWidth() / (double)aNewTextRect.GetWidth();
2764 			double fYScale = (double)aOldTextRect.GetHeight() / (double)aNewTextRect.GetHeight();
2765 			double fRightDiff = (double)( aAdjustedTextRect.Right() - aNewTextRect.Right() ) * fXScale;
2766 			double fLeftDiff  = (double)( aAdjustedTextRect.Left()  - aNewTextRect.Left()  ) * fXScale;
2767 			double fTopDiff   = (double)( aAdjustedTextRect.Top()   - aNewTextRect.Top()   ) * fYScale;
2768 			double fBottomDiff= (double)( aAdjustedTextRect.Bottom()- aNewTextRect.Bottom()) * fYScale;
2769 			aReturnValue.Left() += (sal_Int32)fLeftDiff;
2770 			aReturnValue.Right() += (sal_Int32)fRightDiff;
2771 			aReturnValue.Top() += (sal_Int32)fTopDiff;
2772 			aReturnValue.Bottom() += (sal_Int32)fBottomDiff;
2773 		}
2774 	}
2775 	return aReturnValue;
2776 }
2777 
2778 FASTBOOL SdrObjCustomShape::NbcAdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt)
2779 {
2780 	Rectangle aNewTextRect = ImpCalculateTextFrame( bHgt, bWdt );
2781 	sal_Bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != aRect );
2782 	if ( bRet )
2783 	{
2784 		// taking care of handles that should not been changed
2785 		std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
2786 
2787 		aRect = aNewTextRect;
2788 		SetRectsDirty();
2789 		SetChanged();
2790 
2791 		std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() );
2792 		while ( aIter != aInteractionHandles.end() )
2793 		{
2794 			try
2795 			{
2796 				if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2797 					aIter->xInteraction->setControllerPosition( aIter->aPosition );
2798 			}
2799 			catch ( const uno::RuntimeException& )
2800 			{
2801 			}
2802 			aIter++;
2803 		}
2804 		InvalidateRenderGeometry();
2805 	}
2806 	return bRet;
2807 }
2808 FASTBOOL SdrObjCustomShape::AdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt)
2809 {
2810 	Rectangle aNewTextRect = ImpCalculateTextFrame( bHgt, bWdt );
2811 	sal_Bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != aRect );
2812 	if ( bRet )
2813 	{
2814 		Rectangle aBoundRect0;
2815 		if ( pUserCall )
2816 			aBoundRect0 = GetCurrentBoundRect();
2817 
2818 		// taking care of handles that should not been changed
2819 		std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
2820 
2821 //		SendRepaintBroadcast();
2822 		aRect = aNewTextRect;
2823 		SetRectsDirty();
2824 
2825 		std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() );
2826 		while ( aIter != aInteractionHandles.end() )
2827 		{
2828 			try
2829 			{
2830 				if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2831 					aIter->xInteraction->setControllerPosition( aIter->aPosition );
2832 			}
2833 			catch ( const uno::RuntimeException& )
2834 			{
2835 			}
2836 			aIter++;
2837 		}
2838 
2839 		InvalidateRenderGeometry();
2840 		SetChanged();
2841 //		SendRepaintBroadcast();
2842 		BroadcastObjectChange();
2843 		SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
2844 	}
2845 	return bRet;
2846 }
2847 sal_Bool SdrObjCustomShape::BegTextEdit( SdrOutliner& rOutl )
2848 {
2849 	return SdrTextObj::BegTextEdit( rOutl );
2850 }
2851 void SdrObjCustomShape::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const
2852 {
2853 	Size aPaperMin,aPaperMax;
2854 	Rectangle aViewInit;
2855 	TakeTextAnchorRect( aViewInit );
2856 	if ( aGeo.nDrehWink )
2857 	{
2858 		Point aCenter(aViewInit.Center());
2859 		aCenter-=aViewInit.TopLeft();
2860 		Point aCenter0(aCenter);
2861 		RotatePoint(aCenter,Point(),aGeo.nSin,aGeo.nCos);
2862 		aCenter-=aCenter0;
2863 		aViewInit.Move(aCenter.X(),aCenter.Y());
2864 	}
2865 	Size aAnkSiz(aViewInit.GetSize());
2866 	aAnkSiz.Width()--; aAnkSiz.Height()--; // weil GetSize() ein draufaddiert
2867 	Size aMaxSiz(1000000,1000000);
2868 	if (pModel!=NULL) {
2869 		Size aTmpSiz(pModel->GetMaxObjSize());
2870 		if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width();
2871 		if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height();
2872 	}
2873 	SdrTextHorzAdjust eHAdj(GetTextHorizontalAdjust());
2874 	SdrTextVertAdjust eVAdj(GetTextVerticalAdjust());
2875 
2876 	long nMinWdt = GetMinTextFrameWidth();
2877 	long nMinHgt = GetMinTextFrameHeight();
2878 	long nMaxWdt = GetMaxTextFrameWidth();
2879 	long nMaxHgt = GetMaxTextFrameHeight();
2880 	if (nMinWdt<1) nMinWdt=1;
2881 	if (nMinHgt<1) nMinHgt=1;
2882 	if ( nMaxWdt == 0 || nMaxWdt > aMaxSiz.Width() )
2883 		nMaxWdt = aMaxSiz.Width();
2884 	if ( nMaxHgt == 0 || nMaxHgt > aMaxSiz.Height() )
2885 		nMaxHgt=aMaxSiz.Height();
2886 
2887 	if (((SdrTextWordWrapItem&)(GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue())
2888 	{
2889 		if ( IsVerticalWriting() )
2890 		{
2891 			nMaxHgt = aAnkSiz.Height();
2892 			nMinHgt = nMaxHgt;
2893 		}
2894 		else
2895 		{
2896 			nMaxWdt = aAnkSiz.Width();
2897 			nMinWdt = nMaxWdt;
2898 		}
2899 	}
2900 	aPaperMax.Width()=nMaxWdt;
2901 	aPaperMax.Height()=nMaxHgt;
2902 
2903 	aPaperMin.Width()=nMinWdt;
2904 	aPaperMin.Height()=nMinHgt;
2905 
2906 	if ( pViewMin )
2907 	{
2908 		*pViewMin = aViewInit;
2909 
2910 		long nXFree = aAnkSiz.Width() - aPaperMin.Width();
2911 		if ( eHAdj == SDRTEXTHORZADJUST_LEFT )
2912 			pViewMin->Right() -= nXFree;
2913 		else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT )
2914 			pViewMin->Left() += nXFree;
2915 		else { pViewMin->Left() += nXFree / 2; pViewMin->Right() = pViewMin->Left() + aPaperMin.Width(); }
2916 
2917 		long nYFree = aAnkSiz.Height() - aPaperMin.Height();
2918 		if ( eVAdj == SDRTEXTVERTADJUST_TOP )
2919 			pViewMin->Bottom() -= nYFree;
2920 		else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM )
2921 			pViewMin->Top() += nYFree;
2922 		else { pViewMin->Top() += nYFree / 2; pViewMin->Bottom() = pViewMin->Top() + aPaperMin.Height(); }
2923 	}
2924 
2925 	if( IsVerticalWriting() )
2926 		aPaperMin.Width() = 0;
2927 	else
2928 		aPaperMin.Height() = 0; // #33102#
2929 
2930 	if( eHAdj != SDRTEXTHORZADJUST_BLOCK )
2931 		aPaperMin.Width()=0;
2932 
2933 	// #103516# For complete ver adjust support, set paper min height to 0, here.
2934 	if(SDRTEXTVERTADJUST_BLOCK != eVAdj )
2935 		aPaperMin.Height() = 0;
2936 
2937 	if (pPaperMin!=NULL) *pPaperMin=aPaperMin;
2938 	if (pPaperMax!=NULL) *pPaperMax=aPaperMax;
2939 	if (pViewInit!=NULL) *pViewInit=aViewInit;
2940 }
2941 void SdrObjCustomShape::EndTextEdit( SdrOutliner& rOutl )
2942 {
2943 	SdrTextObj::EndTextEdit( rOutl );
2944 	InvalidateRenderGeometry();
2945 }
2946 void SdrObjCustomShape::TakeTextAnchorRect( Rectangle& rAnchorRect ) const
2947 {
2948 	if ( GetTextBounds( rAnchorRect ) )
2949 	{
2950 		Point aRotateRef( maSnapRect.Center() );
2951 		rAnchorRect.Left()   += GetTextLeftDistance();
2952 		rAnchorRect.Top()    += GetTextUpperDistance();
2953 		rAnchorRect.Right()  -= GetTextRightDistance();
2954 		rAnchorRect.Bottom() -= GetTextLowerDistance();
2955 		ImpJustifyRect( rAnchorRect );
2956 
2957 		if ( rAnchorRect.GetWidth() < 2 )
2958 			rAnchorRect.Right() = rAnchorRect.Left() + 1;	// minimal width is 2
2959 		if ( rAnchorRect.GetHeight() < 2 )
2960 			rAnchorRect.Bottom() = rAnchorRect.Top() + 1;	// minimal height is 2
2961 		if ( aGeo.nDrehWink )
2962 		{
2963 			Point aP( rAnchorRect.TopLeft() );
2964 			RotatePoint( aP, aRotateRef, aGeo.nSin, aGeo. nCos );
2965 			rAnchorRect.SetPos( aP );
2966 		}
2967 	}
2968 	else
2969 		SdrTextObj::TakeTextAnchorRect( rAnchorRect );
2970 }
2971 void SdrObjCustomShape::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, FASTBOOL bNoEditText,
2972 	                           Rectangle* pAnchorRect, sal_Bool /*bLineWidth*/) const
2973 {
2974 	Rectangle aAnkRect; // Rect innerhalb dem geankert wird
2975 	TakeTextAnchorRect(aAnkRect);
2976 	SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
2977 	SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
2978 	sal_uIntPtr nStat0=rOutliner.GetControlWord();
2979 	Size aNullSize;
2980 
2981 	rOutliner.SetControlWord(nStat0|EE_CNTRL_AUTOPAGESIZE);
2982 	rOutliner.SetMinAutoPaperSize(aNullSize);
2983 	sal_Int32 nMaxAutoPaperWidth = 1000000;
2984 	sal_Int32 nMaxAutoPaperHeight= 1000000;
2985 
2986 	long nAnkWdt=aAnkRect.GetWidth();
2987 	long nAnkHgt=aAnkRect.GetHeight();
2988 
2989 	if (((SdrTextWordWrapItem&)(GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue())
2990 	{
2991 		if ( IsVerticalWriting() )
2992 			nMaxAutoPaperHeight = nAnkHgt;
2993 		else
2994 			nMaxAutoPaperWidth = nAnkWdt;
2995 	}
2996 	if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting())
2997 	{
2998 		rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0));
2999 	}
3000 
3001 	if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting())
3002 	{
3003 		rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt));
3004 	}
3005 	rOutliner.SetMaxAutoPaperSize( Size( nMaxAutoPaperWidth, nMaxAutoPaperHeight ) );
3006 	rOutliner.SetPaperSize( aNullSize );
3007 
3008 	// Text in den Outliner stecken - ggf. den aus dem EditOutliner
3009 	OutlinerParaObject* pPara= GetOutlinerParaObject();
3010 	if (pEdtOutl && !bNoEditText)
3011 		pPara=pEdtOutl->CreateParaObject();
3012 
3013 	if (pPara)
3014 	{
3015 		sal_Bool bHitTest = sal_False;
3016 		if( pModel )
3017 			bHitTest = &pModel->GetHitTestOutliner() == &rOutliner;
3018 
3019 		const SdrTextObj* pTestObj = rOutliner.GetTextObj();
3020 		if( !pTestObj || !bHitTest || pTestObj != this ||
3021 		    pTestObj->GetOutlinerParaObject() != GetOutlinerParaObject() )
3022 		{
3023 			if( bHitTest )
3024 				rOutliner.SetTextObj( this );
3025 
3026 			rOutliner.SetUpdateMode(sal_True);
3027 			rOutliner.SetText(*pPara);
3028 		}
3029 	}
3030 	else
3031 	{
3032 		rOutliner.SetTextObj( NULL );
3033 	}
3034 	if (pEdtOutl && !bNoEditText && pPara)
3035 		delete pPara;
3036 
3037 	rOutliner.SetUpdateMode(sal_True);
3038 	rOutliner.SetControlWord(nStat0);
3039 
3040 	SdrText* pText = getActiveText();
3041 	if( pText )
3042 		pText->CheckPortionInfo( rOutliner );
3043 
3044 	Point aTextPos(aAnkRect.TopLeft());
3045 	Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() hat etwas Toleranz drauf, oder?
3046 
3047 	// #106653#
3048 	// For draw objects containing text correct hor/ver alignment if text is bigger
3049 	// than the object itself. Without that correction, the text would always be
3050 		// formatted to the left edge (or top edge when vertical) of the draw object.
3051 
3052 	if( !IsTextFrame() )
3053 	{
3054 		if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting())
3055 		{
3056 			// #110129#
3057 			// Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK,
3058 			// else the alignment is wanted.
3059 			if(SDRTEXTHORZADJUST_BLOCK == eHAdj)
3060 			{
3061 				eHAdj = SDRTEXTHORZADJUST_CENTER;
3062 			}
3063 		}
3064 
3065 		if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting())
3066 		{
3067 			// #110129#
3068 			// Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK,
3069 			// else the alignment is wanted.
3070 			if(SDRTEXTVERTADJUST_BLOCK == eVAdj)
3071 			{
3072 				eVAdj = SDRTEXTVERTADJUST_CENTER;
3073 			}
3074 		}
3075 	}
3076 
3077 	if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT)
3078 	{
3079 		long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width();
3080 		if (eHAdj==SDRTEXTHORZADJUST_CENTER)
3081 			aTextPos.X()+=nFreeWdt/2;
3082 		if (eHAdj==SDRTEXTHORZADJUST_RIGHT)
3083 			aTextPos.X()+=nFreeWdt;
3084 	}
3085 	if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM)
3086 	{
3087 		long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height();
3088 		if (eVAdj==SDRTEXTVERTADJUST_CENTER)
3089 			aTextPos.Y()+=nFreeHgt/2;
3090 		if (eVAdj==SDRTEXTVERTADJUST_BOTTOM)
3091 			aTextPos.Y()+=nFreeHgt;
3092 	}
3093 	if (aGeo.nDrehWink!=0)
3094 		RotatePoint(aTextPos,aAnkRect.TopLeft(),aGeo.nSin,aGeo.nCos);
3095 
3096 	if (pAnchorRect)
3097 		*pAnchorRect=aAnkRect;
3098 
3099 	// rTextRect ist bei ContourFrame in einigen Faellen nicht korrekt
3100 	rTextRect=Rectangle(aTextPos,aTextSiz);
3101 }
3102 
3103 void SdrObjCustomShape::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject)
3104 {
3105 	SdrTextObj::NbcSetOutlinerParaObject( pTextObject );
3106 	SetBoundRectDirty();
3107 	SetRectsDirty(sal_True);
3108 	InvalidateRenderGeometry();
3109 }
3110 
3111 void SdrObjCustomShape::operator=(const SdrObject& rObj)
3112 {
3113 	SdrTextObj::operator=( rObj );
3114 	aName =((SdrObjCustomShape&)rObj).aName;
3115 	fObjectRotation = ((SdrObjCustomShape&)rObj).fObjectRotation;
3116 	InvalidateRenderGeometry();
3117 }
3118 
3119 
3120 void SdrObjCustomShape::TakeObjNameSingul(XubString& rName) const
3121 {
3122 	rName = ImpGetResStr(STR_ObjNameSingulCUSTOMSHAPE);
3123 	String aNm( GetName() );
3124 	if( aNm.Len() )
3125 	{
3126 		rName += sal_Unicode(' ');
3127 		rName += sal_Unicode('\'');
3128 		rName += aNm;
3129 		rName += sal_Unicode('\'');
3130 	}
3131 }
3132 
3133 void SdrObjCustomShape::TakeObjNamePlural(XubString& rName) const
3134 {
3135 	rName=ImpGetResStr(STR_ObjNamePluralCUSTOMSHAPE);
3136 }
3137 
3138 basegfx::B2DPolyPolygon SdrObjCustomShape::TakeXorPoly() const
3139 {
3140 	return GetLineGeometry( (SdrObjCustomShape*)this, sal_False );
3141 }
3142 
3143 basegfx::B2DPolyPolygon SdrObjCustomShape::TakeContour() const
3144 {
3145 	const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
3146 	if ( pSdrObject )
3147 		return pSdrObject->TakeContour();
3148 	return basegfx::B2DPolyPolygon();
3149 }
3150 
3151 SdrObject* SdrObjCustomShape::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const
3152 {
3153 	// #i37011#
3154 	SdrObject* pRetval = 0L;
3155 	SdrObject* pRenderedCustomShape = 0L;
3156 
3157 	if ( !mXRenderedCustomShape.is() )
3158 	{
3159 		// force CustomShape
3160 		((SdrObjCustomShape*)this)->GetSdrObjectFromCustomShape();
3161 	}
3162 
3163 	if ( mXRenderedCustomShape.is() )
3164 	{
3165 		pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape );
3166 	}
3167 
3168 	if ( pRenderedCustomShape )
3169 	{
3170 		SdrObject* pCandidate = pRenderedCustomShape->Clone();
3171 		DBG_ASSERT(pCandidate, "SdrObjCustomShape::DoConvertToPolyObj: Could not clone SdrObject (!)");
3172 		pCandidate->SetModel(GetModel());
3173 		pRetval = pCandidate->DoConvertToPolyObj(bBezier, bAddText);
3174 		SdrObject::Free( pCandidate );
3175 
3176 		if(pRetval)
3177 		{
3178 			const sal_Bool bShadow(((SdrShadowItem&)GetMergedItem(SDRATTR_SHADOW)).GetValue());
3179 			if(bShadow)
3180 			{
3181 				pRetval->SetMergedItem(SdrShadowItem(sal_True));
3182 			}
3183 		}
3184 
3185 		if(bAddText && HasText() && !IsTextPath())
3186 		{
3187 			pRetval = ImpConvertAddText(pRetval, bBezier);
3188 		}
3189 	}
3190 
3191 	return pRetval;
3192 }
3193 
3194 void SdrObjCustomShape::NbcSetStyleSheet( SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr )
3195 {
3196 	// #i40944#
3197 	InvalidateRenderGeometry();
3198 	SdrObject::NbcSetStyleSheet( pNewStyleSheet, bDontRemoveHardAttr );
3199 }
3200 
3201 void SdrObjCustomShape::SetPage( SdrPage* pNewPage )
3202 {
3203 	SdrTextObj::SetPage( pNewPage );
3204 
3205 	if( pNewPage )
3206 	{
3207 		// invalidating rectangles by SetRectsDirty is not sufficient,
3208 		// AdjustTextFrameWidthAndHeight() also has to be made, both
3209 		// actions are done by NbcSetSnapRect
3210 		Rectangle aTmp( aRect );	//creating temporary rectangle #i61108#
3211 		NbcSetSnapRect( aTmp );
3212 	}
3213 }
3214 
3215 SdrObjGeoData* SdrObjCustomShape::NewGeoData() const
3216 {
3217 	return new SdrAShapeObjGeoData;
3218 }
3219 
3220 void SdrObjCustomShape::SaveGeoData(SdrObjGeoData& rGeo) const
3221 {
3222 	SdrTextObj::SaveGeoData( rGeo );
3223 	SdrAShapeObjGeoData& rAGeo=(SdrAShapeObjGeoData&)rGeo;
3224 	rAGeo.fObjectRotation = fObjectRotation;
3225 	rAGeo.bMirroredX = IsMirroredX();
3226 	rAGeo.bMirroredY = IsMirroredY();
3227 
3228 	const rtl::OUString	sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) );
3229 	Any* pAny( ( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ).GetPropertyValueByName( sAdjustmentValues ) );
3230 	if ( pAny )
3231 		*pAny >>= rAGeo.aAdjustmentSeq;
3232 }
3233 
3234 void SdrObjCustomShape::RestGeoData(const SdrObjGeoData& rGeo)
3235 {
3236 	SdrTextObj::RestGeoData( rGeo );
3237 	SdrAShapeObjGeoData& rAGeo=(SdrAShapeObjGeoData&)rGeo;
3238 	fObjectRotation = rAGeo.fObjectRotation;
3239 	SetMirroredX( rAGeo.bMirroredX );
3240 	SetMirroredY( rAGeo.bMirroredY );
3241 
3242 	SdrCustomShapeGeometryItem rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
3243 	const rtl::OUString	sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) );
3244 	PropertyValue aPropVal;
3245 	aPropVal.Name = sAdjustmentValues;
3246 	aPropVal.Value <<= rAGeo.aAdjustmentSeq;
3247 	rGeometryItem.SetPropertyValue( aPropVal );
3248 	SetMergedItem( rGeometryItem );
3249 
3250 	InvalidateRenderGeometry();
3251 }
3252 
3253 void SdrObjCustomShape::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
3254 {
3255 	// break up matrix
3256 	basegfx::B2DTuple aScale;
3257 	basegfx::B2DTuple aTranslate;
3258 	double fRotate, fShearX;
3259 	rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
3260 
3261 	// #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
3262 	// in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
3263 	if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
3264 	{
3265 		aScale.setX(fabs(aScale.getX()));
3266 		aScale.setY(fabs(aScale.getY()));
3267 		fRotate = fmod(fRotate + F_PI, F_2PI);
3268 	}
3269 
3270 	// reset object shear and rotations
3271 	aGeo.nDrehWink = 0;
3272 	aGeo.RecalcSinCos();
3273 	aGeo.nShearWink = 0;
3274 	aGeo.RecalcTan();
3275 
3276 	// force metric to pool metric
3277 	SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0);
3278 	if(eMapUnit != SFX_MAPUNIT_100TH_MM)
3279 	{
3280 		switch(eMapUnit)
3281 		{
3282 			case SFX_MAPUNIT_TWIP :
3283 			{
3284 				// position
3285 				aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
3286 				aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
3287 
3288 				// size
3289 				aScale.setX(ImplMMToTwips(aScale.getX()));
3290 				aScale.setY(ImplMMToTwips(aScale.getY()));
3291 
3292 				break;
3293 			}
3294 			default:
3295 			{
3296 				DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
3297 			}
3298 		}
3299 	}
3300 
3301 	// if anchor is used, make position relative to it
3302 	if( pModel && pModel->IsWriter() )
3303 	{
3304 		if(GetAnchorPos().X() || GetAnchorPos().Y())
3305 		{
3306 			aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3307 		}
3308 	}
3309 
3310 	// build and set BaseRect (use scale)
3311 	Point aPoint = Point();
3312 	Size aSize(FRound(aScale.getX()), FRound(aScale.getY()));
3313 	Rectangle aBaseRect(aPoint, aSize);
3314 	SetSnapRect(aBaseRect);
3315 
3316 	// shear?
3317 	if(!basegfx::fTools::equalZero(fShearX))
3318 	{
3319 		GeoStat aGeoStat;
3320 		aGeoStat.nShearWink = FRound((atan(fShearX) / F_PI180) * 100.0);
3321 		aGeoStat.RecalcTan();
3322 		Shear(Point(), aGeoStat.nShearWink, aGeoStat.nTan, sal_False);
3323 	}
3324 
3325 	// rotation?
3326     if(!basegfx::fTools::equalZero(fRotate))
3327 	{
3328 		GeoStat aGeoStat;
3329 
3330         // #i78696#
3331         // fRotate is mathematically correct, but aGeoStat.nDrehWink is
3332         // mirrored -> mirror value here
3333 		aGeoStat.nDrehWink = NormAngle360(FRound(-fRotate / F_PI18000));
3334 		aGeoStat.RecalcSinCos();
3335 		Rotate(Point(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos);
3336 	}
3337 
3338 	// translate?
3339     if(!aTranslate.equalZero())
3340 	{
3341 		Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY())));
3342 	}
3343 }
3344 
3345 // taking fObjectRotation instead of aGeo.nWink
3346 sal_Bool SdrObjCustomShape::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
3347 {
3348 	// get turn and shear
3349 //	double fRotate = (aGeo.nDrehWink / 100.0) * F_PI180;
3350 	double fRotate = fObjectRotation * F_PI180;
3351 	double fShearX = (aGeo.nShearWink / 100.0) * F_PI180;
3352 
3353 	// get aRect, this is the unrotated snaprect
3354 	Rectangle aRectangle(aRect);
3355 
3356 	sal_Bool bMirroredX = IsMirroredX();
3357 	sal_Bool bMirroredY = IsMirroredY();
3358 	if ( bMirroredX || bMirroredY )
3359 	{	// we have to retrieve the unmirrored rect
3360 
3361 		GeoStat aNewGeo( aGeo );
3362 
3363 		if ( bMirroredX )
3364 		{
3365 			Polygon aPol( Rect2Poly( aRect, aNewGeo ) );
3366 			Rectangle aBoundRect( aPol.GetBoundRect() );
3367 
3368 			Point aRef1( ( aBoundRect.Left() + aBoundRect.Right() ) >> 1, aBoundRect.Top() );
3369 			Point aRef2( aRef1.X(), aRef1.Y() + 1000 );
3370 			sal_uInt16 i;
3371 			sal_uInt16 nPntAnz=aPol.GetSize();
3372 			for (i=0; i<nPntAnz; i++)
3373 			{
3374 				MirrorPoint(aPol[i],aRef1,aRef2);
3375 			}
3376 			// Polygon wenden und etwas schieben
3377 			Polygon aPol0(aPol);
3378 			aPol[0]=aPol0[1];
3379 			aPol[1]=aPol0[0];
3380 			aPol[2]=aPol0[3];
3381 			aPol[3]=aPol0[2];
3382 			aPol[4]=aPol0[1];
3383 			Poly2Rect(aPol,aRectangle,aNewGeo);
3384 		}
3385 		if ( bMirroredY )
3386 		{
3387 			Polygon aPol( Rect2Poly( aRectangle, aNewGeo ) );
3388 			Rectangle aBoundRect( aPol.GetBoundRect() );
3389 
3390 			Point aRef1( aBoundRect.Left(), ( aBoundRect.Top() + aBoundRect.Bottom() ) >> 1 );
3391 			Point aRef2( aRef1.X() + 1000, aRef1.Y() );
3392 			sal_uInt16 i;
3393 			sal_uInt16 nPntAnz=aPol.GetSize();
3394 			for (i=0; i<nPntAnz; i++)
3395 			{
3396 				MirrorPoint(aPol[i],aRef1,aRef2);
3397 			}
3398 			// Polygon wenden und etwas schieben
3399 			Polygon aPol0(aPol);
3400 			aPol[0]=aPol0[1];
3401 			aPol[1]=aPol0[0];
3402 			aPol[2]=aPol0[3];
3403 			aPol[3]=aPol0[2];
3404 			aPol[4]=aPol0[1];
3405 			Poly2Rect(aPol,aRectangle,aNewGeo);
3406 		}
3407 	}
3408 
3409 	// fill other values
3410 	basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight());
3411 	basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top());
3412 
3413 	// position maybe relative to anchorpos, convert
3414 	if( pModel && pModel->IsWriter() )
3415 	{
3416 		if(GetAnchorPos().X() || GetAnchorPos().Y())
3417 		{
3418 			aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3419 		}
3420 	}
3421 
3422 	// force MapUnit to 100th mm
3423 	SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0);
3424 	if(eMapUnit != SFX_MAPUNIT_100TH_MM)
3425 	{
3426 		switch(eMapUnit)
3427 		{
3428 			case SFX_MAPUNIT_TWIP :
3429 			{
3430 				// postion
3431 				aTranslate.setX(ImplTwipsToMM(aTranslate.getX()));
3432 				aTranslate.setY(ImplTwipsToMM(aTranslate.getY()));
3433 
3434 				// size
3435 				aScale.setX(ImplTwipsToMM(aScale.getX()));
3436 				aScale.setY(ImplTwipsToMM(aScale.getY()));
3437 
3438 				break;
3439 			}
3440 			default:
3441 			{
3442 				DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!");
3443 			}
3444 		}
3445 	}
3446 
3447 	// build matrix
3448 	rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
3449 		aScale,
3450 		basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX),
3451 		basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate,
3452 		aTranslate);
3453 
3454 	return sal_False;
3455 }
3456 
3457 sdr::contact::ViewContact* SdrObjCustomShape::CreateObjectSpecificViewContact()
3458 {
3459 	return new sdr::contact::ViewContactOfSdrObjCustomShape(*this);
3460 }
3461 
3462 // #i33136#
3463 bool SdrObjCustomShape::doConstructOrthogonal(const ::rtl::OUString& rName)
3464 {
3465 	bool bRetval(false);
3466 	static ::rtl::OUString Imps_sNameASOrtho_quadrat( RTL_CONSTASCII_USTRINGPARAM( "quadrat" ) );
3467 	static ::rtl::OUString Imps_sNameASOrtho_round_quadrat( RTL_CONSTASCII_USTRINGPARAM( "round-quadrat" ) );
3468 	static ::rtl::OUString Imps_sNameASOrtho_circle( RTL_CONSTASCII_USTRINGPARAM( "circle" ) );
3469 	static ::rtl::OUString Imps_sNameASOrtho_circle_pie( RTL_CONSTASCII_USTRINGPARAM( "circle-pie" ) );
3470 	static ::rtl::OUString Imps_sNameASOrtho_ring( RTL_CONSTASCII_USTRINGPARAM( "ring" ) );
3471 
3472 	if(Imps_sNameASOrtho_quadrat.equalsIgnoreAsciiCase(rName))
3473 	{
3474 		bRetval = true;
3475 	}
3476 	else if(Imps_sNameASOrtho_round_quadrat.equalsIgnoreAsciiCase(rName))
3477 	{
3478 		bRetval = true;
3479 	}
3480 	else if(Imps_sNameASOrtho_circle.equalsIgnoreAsciiCase(rName))
3481 	{
3482 		bRetval = true;
3483 	}
3484 	else if(Imps_sNameASOrtho_circle_pie.equalsIgnoreAsciiCase(rName))
3485 	{
3486 		bRetval = true;
3487 	}
3488 	else if(Imps_sNameASOrtho_ring.equalsIgnoreAsciiCase(rName))
3489 	{
3490 		bRetval = true;
3491 	}
3492 
3493 	return bRetval;
3494 }
3495 
3496 // #i37011# centralize throw-away of render geometry
3497 void SdrObjCustomShape::InvalidateRenderGeometry()
3498 {
3499 	mXRenderedCustomShape = 0L;
3500     SdrObject::Free( mpLastShadowGeometry );
3501 	mpLastShadowGeometry = 0L;
3502 }
3503 
3504 // eof
3505