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