Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / svx / source / svdraw / svdoashp.cxx
blob8f7b0e2e5166259211b67fbac63101ebf22a623d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/svdoashp.hxx>
21 #include "svx/unoapi.hxx"
22 #include <svx/unoshape.hxx>
23 #include <ucbhelper/content.hxx>
24 #include <unotools/datetime.hxx>
25 #include <sfx2/lnkbase.hxx>
26 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
27 #include <com/sun/star/drawing/XShape.hpp>
28 #include <com/sun/star/drawing/XCustomShapeEngine.hpp>
29 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/awt/Rectangle.hpp>
32 #include <comphelper/processfactory.hxx>
33 #include <svl/urihelper.hxx>
34 #include <com/sun/star/uno/Sequence.h>
35 #include <svx/svdogrp.hxx>
36 #include <tools/helpers.hxx>
37 #include <svx/svddrag.hxx>
38 #include <svx/xpool.hxx>
39 #include <svx/xpoly.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <svx/svdpage.hxx>
42 #include "svx/svditer.hxx"
43 #include <svx/svdobj.hxx>
44 #include <svx/svdtrans.hxx>
45 #include <svx/svdetc.hxx>
46 #include <svx/svdoedge.hxx>
47 #include "svdglob.hxx"
48 #include "svx/svdstr.hrc"
49 #include <editeng/eeitem.hxx>
50 #include "editeng/editstat.hxx"
51 #include <svx/svdoutl.hxx>
52 #include <editeng/outlobj.hxx>
53 #include <svx/sdtfchim.hxx>
54 #include "svx/EnhancedCustomShapeGeometry.hxx"
55 #include "svx/EnhancedCustomShapeTypeNames.hxx"
56 #include "svx/EnhancedCustomShape2d.hxx"
57 #include <com/sun/star/beans/PropertyValues.hpp>
58 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
59 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
60 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
61 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
62 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
63 #include <editeng/writingmodeitem.hxx>
64 #include <svx/xlnclit.hxx>
65 #include <svx/svxids.hrc>
66 #include <svl/whiter.hxx>
67 #include <sdr/properties/customshapeproperties.hxx>
68 #include <sdr/contact/viewcontactofsdrobjcustomshape.hxx>
69 #include <svx/xlntrit.hxx>
70 #include <svx/xfltrit.hxx>
71 #include <svx/xflclit.hxx>
72 #include <svx/xflgrit.hxx>
73 #include <svx/xflhtit.hxx>
74 #include <svx/xbtmpit.hxx>
75 #include <vcl/bmpacc.hxx>
76 #include <svx/svdview.hxx>
77 #include <basegfx/polygon/b2dpolypolygontools.hxx>
78 #include <basegfx/matrix/b2dhommatrix.hxx>
79 #include <basegfx/matrix/b2dhommatrixtools.hxx>
80 #include <basegfx/tools/unotools.hxx>
81 #include "svdconv.hxx"
83 using namespace ::com::sun::star;
84 using namespace ::com::sun::star::uno;
85 using namespace ::com::sun::star::lang;
86 using namespace ::com::sun::star::beans;
87 using namespace ::com::sun::star::drawing;
89 static void lcl_ShapeSegmentFromBinary( EnhancedCustomShapeSegment& rSegInfo, sal_uInt16 nSDat )
91 switch( nSDat >> 8 )
93 case 0x00 :
94 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::LINETO;
95 rSegInfo.Count = nSDat & 0xff;
96 if ( !rSegInfo.Count )
97 rSegInfo.Count = 1;
98 break;
99 case 0x20 :
100 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CURVETO;
101 rSegInfo.Count = nSDat & 0xff;
102 if ( !rSegInfo.Count )
103 rSegInfo.Count = 1;
104 break;
105 case 0x40 :
106 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::MOVETO;
107 rSegInfo.Count = nSDat & 0xff;
108 if ( !rSegInfo.Count )
109 rSegInfo.Count = 1;
110 break;
111 case 0x60 :
112 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
113 rSegInfo.Count = 0;
114 break;
115 case 0x80 :
116 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
117 rSegInfo.Count = 0;
118 break;
119 case 0xa1 :
120 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO;
121 rSegInfo.Count = ( nSDat & 0xff ) / 3;
122 break;
123 case 0xa2 :
124 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE;
125 rSegInfo.Count = ( nSDat & 0xff ) / 3;
126 break;
127 case 0xa3 :
128 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARCTO;
129 rSegInfo.Count = ( nSDat & 0xff ) >> 2;
130 break;
131 case 0xa4 :
132 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARC;
133 rSegInfo.Count = ( nSDat & 0xff ) >> 2;
134 break;
135 case 0xa5 :
136 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO;
137 rSegInfo.Count = ( nSDat & 0xff ) >> 2;
138 break;
139 case 0xa6 :
140 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC;
141 rSegInfo.Count = ( nSDat & 0xff ) >> 2;
142 break;
143 case 0xa7 :
144 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX;
145 rSegInfo.Count = nSDat & 0xff;
146 break;
147 case 0xa8 :
148 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY;
149 rSegInfo.Count = nSDat & 0xff;
150 break;
151 case 0xaa :
152 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOFILL;
153 rSegInfo.Count = 0;
154 break;
155 case 0xab :
156 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOSTROKE;
157 rSegInfo.Count = 0;
158 break;
159 default:
160 case 0xf8 :
161 rSegInfo.Command = EnhancedCustomShapeSegmentCommand::UNKNOWN;
162 rSegInfo.Count = nSDat;
163 break;
165 return;
168 static MSO_SPT ImpGetCustomShapeType( const SdrObjCustomShape& rCustoShape )
170 MSO_SPT eRetValue = mso_sptNil;
172 OUString aEngine( ( (SdrCustomShapeEngineItem&)rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ) ).GetValue() );
173 if ( aEngine.isEmpty() || aEngine == "com.sun.star.drawing.EnhancedCustomShapeEngine" )
175 OUString sShapeType;
176 const OUString sType( "Type" );
177 SdrCustomShapeGeometryItem& rGeometryItem( (SdrCustomShapeGeometryItem&)rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
178 Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
179 if ( pAny && ( *pAny >>= sShapeType ) )
180 eRetValue = EnhancedCustomShapeTypeNames::Get( sShapeType );
182 return eRetValue;
185 static bool ImpVerticalSwitch( const SdrObjCustomShape& rCustoShape )
187 bool bRet = false;
188 MSO_SPT eShapeType( ImpGetCustomShapeType( rCustoShape ) );
189 switch( eShapeType )
191 case mso_sptAccentBorderCallout90 : // 2 ortho
192 case mso_sptBorderCallout1 : // 2 diag
193 case mso_sptBorderCallout2 : // 3
195 bRet = true;
197 break;
198 default: break;
200 return bRet;
203 // #i37011# create a clone with all attributes changed to shadow attributes
204 // and translation executed, too.
205 SdrObject* ImpCreateShadowObjectClone(const SdrObject& rOriginal, const SfxItemSet& rOriginalSet)
207 SdrObject* pRetval = 0L;
208 const bool bShadow(((SdrShadowItem&)rOriginalSet.Get(SDRATTR_SHADOW)).GetValue());
210 if(bShadow)
212 // create a shadow representing object
213 const sal_Int32 nXDist(((SdrShadowXDistItem&)(rOriginalSet.Get(SDRATTR_SHADOWXDIST))).GetValue());
214 const sal_Int32 nYDist(((SdrShadowYDistItem&)(rOriginalSet.Get(SDRATTR_SHADOWYDIST))).GetValue());
215 const ::Color aShadowColor(((SdrShadowColorItem&)(rOriginalSet.Get(SDRATTR_SHADOWCOLOR))).GetColorValue());
216 const sal_uInt16 nShadowTransparence(((SdrShadowTransparenceItem&)(rOriginalSet.Get(SDRATTR_SHADOWTRANSPARENCE))).GetValue());
217 pRetval = rOriginal.Clone();
218 DBG_ASSERT(pRetval, "ImpCreateShadowObjectClone: Could not clone object (!)");
220 // look for used stuff
221 SdrObjListIter aIterator(rOriginal);
222 bool bLineUsed(false);
223 bool bAllFillUsed(false);
224 bool bSolidFillUsed(false);
225 bool bGradientFillUsed(false);
226 bool bHatchFillUsed(false);
227 bool bBitmapFillUsed(false);
229 while(aIterator.IsMore())
231 SdrObject* pObj = aIterator.Next();
232 XFillStyle eFillStyle = ((XFillStyleItem&)(pObj->GetMergedItem(XATTR_FILLSTYLE))).GetValue();
234 if(!bLineUsed)
236 XLineStyle eLineStyle = ((XLineStyleItem&)(pObj->GetMergedItem(XATTR_LINESTYLE))).GetValue();
238 if(XLINE_NONE != eLineStyle)
240 bLineUsed = true;
244 if(!bAllFillUsed)
246 if(!bSolidFillUsed && XFILL_SOLID == eFillStyle)
248 bSolidFillUsed = true;
249 bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
251 if(!bGradientFillUsed && XFILL_GRADIENT == eFillStyle)
253 bGradientFillUsed = true;
254 bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
256 if(!bHatchFillUsed && XFILL_HATCH == eFillStyle)
258 bHatchFillUsed = true;
259 bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
261 if(!bBitmapFillUsed && XFILL_BITMAP == eFillStyle)
263 bBitmapFillUsed = true;
264 bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed);
269 // translate to shadow coordinates
270 pRetval->NbcMove(Size(nXDist, nYDist));
272 // set items as needed
273 SfxItemSet aTempSet(rOriginalSet);
275 // if a SvxWritingModeItem (Top->Bottom) is set the text object
276 // is creating a paraobject, but paraobjects can not be created without model. So
277 // we are preventing the crash by setting the writing mode always left to right,
278 // this is not bad since our shadow geometry does not contain text.
279 aTempSet.Put( SvxWritingModeItem( com::sun::star::text::WritingMode_LR_TB, SDRATTR_TEXTDIRECTION ) );
281 // no shadow
282 aTempSet.Put(SdrShadowItem(false));
283 aTempSet.Put(SdrShadowXDistItem(0L));
284 aTempSet.Put(SdrShadowYDistItem(0L));
286 // line color and transparency like shadow
287 if(bLineUsed)
289 aTempSet.Put(XLineColorItem(OUString(), aShadowColor));
290 aTempSet.Put(XLineTransparenceItem(nShadowTransparence));
293 // fill color and transparency like shadow
294 if(bSolidFillUsed)
296 aTempSet.Put(XFillColorItem(OUString(), aShadowColor));
297 aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
300 // gradient and transparency like shadow
301 if(bGradientFillUsed)
303 XGradient aGradient(((XFillGradientItem&)(rOriginalSet.Get(XATTR_FILLGRADIENT))).GetGradientValue());
304 sal_uInt8 nStartLuminance(aGradient.GetStartColor().GetLuminance());
305 sal_uInt8 nEndLuminance(aGradient.GetEndColor().GetLuminance());
307 if(aGradient.GetStartIntens() != 100)
309 nStartLuminance = (sal_uInt8)(nStartLuminance * ((double)aGradient.GetStartIntens() / 100.0));
312 if(aGradient.GetEndIntens() != 100)
314 nEndLuminance = (sal_uInt8)(nEndLuminance * ((double)aGradient.GetEndIntens() / 100.0));
317 ::Color aStartColor(
318 (sal_uInt8)((nStartLuminance * aShadowColor.GetRed()) / 256),
319 (sal_uInt8)((nStartLuminance * aShadowColor.GetGreen()) / 256),
320 (sal_uInt8)((nStartLuminance * aShadowColor.GetBlue()) / 256));
322 ::Color aEndColor(
323 (sal_uInt8)((nEndLuminance * aShadowColor.GetRed()) / 256),
324 (sal_uInt8)((nEndLuminance * aShadowColor.GetGreen()) / 256),
325 (sal_uInt8)((nEndLuminance * aShadowColor.GetBlue()) / 256));
327 aGradient.SetStartColor(aStartColor);
328 aGradient.SetEndColor(aEndColor);
329 aTempSet.Put(XFillGradientItem(aGradient));
330 aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
333 // hatch and transparency like shadow
334 if(bHatchFillUsed)
336 XHatch aHatch(((XFillHatchItem&)(rOriginalSet.Get(XATTR_FILLHATCH))).GetHatchValue());
337 aHatch.SetColor(aShadowColor);
338 aTempSet.Put(XFillHatchItem(aTempSet.GetPool(), aHatch));
339 aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
342 // bitmap and transparency like shadow
343 if(bBitmapFillUsed)
345 GraphicObject aGraphicObject(((XFillBitmapItem&)(rOriginalSet.Get(XATTR_FILLBITMAP))).GetGraphicObject());
346 const BitmapEx aBitmapEx(aGraphicObject.GetGraphic().GetBitmapEx());
347 Bitmap aBitmap(aBitmapEx.GetBitmap());
349 if(!aBitmap.IsEmpty())
351 BitmapReadAccess* pReadAccess = aBitmap.AcquireReadAccess();
353 if(pReadAccess)
355 Bitmap aDestBitmap(aBitmap.GetSizePixel(), 24L);
356 BitmapWriteAccess* pWriteAccess = aDestBitmap.AcquireWriteAccess();
358 if(pWriteAccess)
360 for(sal_Int32 y(0L); y < pReadAccess->Height(); y++)
362 for(sal_Int32 x(0L); x < pReadAccess->Width(); x++)
364 sal_uInt16 nLuminance((sal_uInt16)pReadAccess->GetLuminance(y, x) + 1);
365 const BitmapColor aDestColor(
366 (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetRed()) >> 8L),
367 (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetGreen()) >> 8L),
368 (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetBlue()) >> 8L));
369 pWriteAccess->SetPixel(y, x, aDestColor);
373 aDestBitmap.ReleaseAccess(pWriteAccess);
376 aBitmap.ReleaseAccess(pReadAccess);
378 if(aBitmapEx.IsTransparent())
380 if(aBitmapEx.IsAlpha())
382 aGraphicObject.SetGraphic(Graphic(BitmapEx(aDestBitmap, aBitmapEx.GetAlpha())));
384 else
386 aGraphicObject.SetGraphic(Graphic(BitmapEx(aDestBitmap, aBitmapEx.GetMask())));
389 else
391 aGraphicObject.SetGraphic(Graphic(aDestBitmap));
396 aTempSet.Put(XFillBitmapItem(aTempSet.GetPool(), aGraphicObject));
397 aTempSet.Put(XFillTransparenceItem(nShadowTransparence));
400 // set attributes and paint shadow object
401 pRetval->SetMergedItemSet( aTempSet );
403 return pRetval;
408 Reference< XCustomShapeEngine > SdrObjCustomShape::GetCustomShapeEngine() const
410 if (mxCustomShapeEngine.is())
411 return mxCustomShapeEngine;
413 OUString aEngine(((SdrCustomShapeEngineItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE )).GetValue());
414 if ( aEngine.isEmpty() )
415 aEngine = "com.sun.star.drawing.EnhancedCustomShapeEngine";
417 Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
419 Reference< XShape > aXShape = GetXShapeForSdrObject(const_cast<SdrObjCustomShape*>(this));
420 if ( aXShape.is() )
422 Sequence< Any > aArgument( 1 );
423 Sequence< PropertyValue > aPropValues( 1 );
424 aPropValues[ 0 ].Name = "CustomShape";
425 aPropValues[ 0 ].Value <<= aXShape;
426 aArgument[ 0 ] <<= aPropValues;
427 Reference< XInterface > xInterface( xContext->getServiceManager()->createInstanceWithArgumentsAndContext( aEngine, aArgument, xContext ) );
428 if ( xInterface.is() )
429 mxCustomShapeEngine = Reference< XCustomShapeEngine >( xInterface, UNO_QUERY );
432 return mxCustomShapeEngine;
435 const SdrObject* SdrObjCustomShape::GetSdrObjectFromCustomShape() const
437 if ( !mXRenderedCustomShape.is() )
439 Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine() );
440 if ( xCustomShapeEngine.is() )
441 ((SdrObjCustomShape*)this)->mXRenderedCustomShape = xCustomShapeEngine->render();
443 SdrObject* pRenderedCustomShape = mXRenderedCustomShape.is()
444 ? GetSdrObjectFromXShape( mXRenderedCustomShape )
445 : NULL;
446 return pRenderedCustomShape;
449 // #i37011# Shadow geometry creation
450 const SdrObject* SdrObjCustomShape::GetSdrObjectShadowFromCustomShape() const
452 if(!mpLastShadowGeometry)
454 const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
455 if(pSdrObject)
457 const SfxItemSet& rOriginalSet = GetObjectItemSet();
458 const bool bShadow(((SdrShadowItem&)rOriginalSet.Get( SDRATTR_SHADOW )).GetValue());
460 if(bShadow)
462 // create a clone with all attributes changed to shadow attributes
463 // and translation executed, too.
464 ((SdrObjCustomShape*)this)->mpLastShadowGeometry = ImpCreateShadowObjectClone(*pSdrObject, rOriginalSet);
469 return mpLastShadowGeometry;
472 bool SdrObjCustomShape::IsTextPath() const
474 const OUString sTextPath( "TextPath" );
475 bool bTextPathOn = false;
476 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
477 Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath );
478 if ( pAny )
479 *pAny >>= bTextPathOn;
480 return bTextPathOn;
483 bool SdrObjCustomShape::UseNoFillStyle() const
485 bool bRet = false;
486 OUString sShapeType;
487 const OUString sType( "Type" );
488 SdrCustomShapeGeometryItem& rGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
489 Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
490 if ( pAny )
491 *pAny >>= sShapeType;
492 bRet = IsCustomShapeFilledByDefault( EnhancedCustomShapeTypeNames::Get( sType ) ) == false;
494 return bRet;
497 bool SdrObjCustomShape::IsMirroredX() const
499 bool bMirroredX = false;
500 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
501 const OUString sMirroredX( "MirroredX" );
502 com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX );
503 if ( pAny )
504 *pAny >>= bMirroredX;
505 return bMirroredX;
507 bool SdrObjCustomShape::IsMirroredY() const
509 bool bMirroredY = false;
510 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
511 const OUString sMirroredY( "MirroredY" );
512 com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY );
513 if ( pAny )
514 *pAny >>= bMirroredY;
515 return bMirroredY;
517 void SdrObjCustomShape::SetMirroredX( const bool bMirrorX )
519 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
520 const OUString sMirroredX( "MirroredX" );
521 PropertyValue aPropVal;
522 aPropVal.Name = sMirroredX;
523 aPropVal.Value <<= bMirrorX;
524 aGeometryItem.SetPropertyValue( aPropVal );
525 SetMergedItem( aGeometryItem );
527 void SdrObjCustomShape::SetMirroredY( const bool bMirrorY )
529 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
530 const OUString sMirroredY( "MirroredY" );
531 PropertyValue aPropVal;
532 aPropVal.Name = sMirroredY;
533 aPropVal.Value <<= bMirrorY;
534 aGeometryItem.SetPropertyValue( aPropVal );
535 SetMergedItem( aGeometryItem );
538 double SdrObjCustomShape::GetObjectRotation() const
540 return fObjectRotation;
543 bool SdrObjCustomShape::IsPostRotate() const
545 const com::sun::star::uno::Any* pAny;
546 bool bPostRotate = false;
547 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
548 pAny = rGeometryItem.GetPropertyValueByName( "IsPostRotateAngle" );
549 if ( pAny )
550 *pAny >>= bPostRotate;
551 return bPostRotate;
554 double SdrObjCustomShape::GetExtraTextRotation( const bool bPreRotation ) const
556 const com::sun::star::uno::Any* pAny;
557 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
558 const OUString sTextRotateAngle( "TextRotateAngle" );
559 const OUString sTextPreRotateAngle( "TextPreRotateAngle" );
560 pAny = rGeometryItem.GetPropertyValueByName( bPreRotation ? sTextPreRotateAngle : sTextRotateAngle );
561 double fExtraTextRotateAngle = 0.0;
562 if ( pAny )
563 *pAny >>= fExtraTextRotateAngle;
564 return fExtraTextRotateAngle;
567 bool SdrObjCustomShape::GetTextBounds( Rectangle& rTextBound ) const
569 bool bRet = false;
571 Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine() );
572 if ( xCustomShapeEngine.is() )
574 awt::Rectangle aR( xCustomShapeEngine->getTextBounds() );
575 if ( aR.Width > 1 && aR.Height > 1 )
577 rTextBound = Rectangle( Point( aR.X, aR.Y ), Size( aR.Width, aR.Height ) );
578 bRet = true;
581 return bRet;
583 basegfx::B2DPolyPolygon SdrObjCustomShape::GetLineGeometry( const SdrObjCustomShape* pCustomShape, const bool bBezierAllowed )
585 basegfx::B2DPolyPolygon aRetval;
586 Reference< XCustomShapeEngine > xCustomShapeEngine( pCustomShape->GetCustomShapeEngine() );
587 if ( xCustomShapeEngine.is() )
589 com::sun::star::drawing::PolyPolygonBezierCoords aBezierCoords = xCustomShapeEngine->getLineGeometry();
592 aRetval = basegfx::unotools::polyPolygonBezierToB2DPolyPolygon( aBezierCoords );
593 if ( !bBezierAllowed && aRetval.areControlPointsUsed())
595 aRetval = basegfx::tools::adaptiveSubdivideByAngle(aRetval);
598 catch ( const com::sun::star::lang::IllegalArgumentException & )
602 return aRetval;
605 std::vector< SdrCustomShapeInteraction > SdrObjCustomShape::GetInteractionHandles( const SdrObjCustomShape* pCustomShape ) const
607 std::vector< SdrCustomShapeInteraction > xRet;
610 Reference< XCustomShapeEngine > xCustomShapeEngine( pCustomShape->GetCustomShapeEngine() );
611 if ( xCustomShapeEngine.is() )
613 int i;
614 Sequence< Reference< XCustomShapeHandle > > xInteractionHandles( xCustomShapeEngine->getInteraction() );
615 for ( i = 0; i < xInteractionHandles.getLength(); i++ )
617 if ( xInteractionHandles[ i ].is() )
619 SdrCustomShapeInteraction aSdrCustomShapeInteraction;
620 aSdrCustomShapeInteraction.xInteraction = xInteractionHandles[ i ];
621 aSdrCustomShapeInteraction.aPosition = xInteractionHandles[ i ]->getPosition();
623 sal_Int32 nMode = 0;
624 switch( ImpGetCustomShapeType( *this ) )
626 case mso_sptAccentBorderCallout90 : // 2 ortho
628 if ( !i )
629 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
630 else if ( i == 1)
631 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE | CUSTOMSHAPE_HANDLE_ORTHO4;
633 break;
635 case mso_sptWedgeRectCallout :
636 case mso_sptWedgeRRectCallout :
637 case mso_sptCloudCallout :
638 case mso_sptWedgeEllipseCallout :
640 if ( !i )
641 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED;
643 break;
645 case mso_sptBorderCallout1 : // 2 diag
647 if ( !i )
648 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
649 else if ( i == 1 )
650 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE;
652 break;
653 case mso_sptBorderCallout2 : // 3
655 if ( !i )
656 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
657 else if ( i == 2 )
658 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE;
660 break;
661 case mso_sptCallout90 :
662 case mso_sptAccentCallout90 :
663 case mso_sptBorderCallout90 :
664 case mso_sptCallout1 :
665 case mso_sptCallout2 :
666 case mso_sptCallout3 :
667 case mso_sptAccentCallout1 :
668 case mso_sptAccentCallout2 :
669 case mso_sptAccentCallout3 :
670 case mso_sptBorderCallout3 :
671 case mso_sptAccentBorderCallout1 :
672 case mso_sptAccentBorderCallout2 :
673 case mso_sptAccentBorderCallout3 :
675 if ( !i )
676 nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED;
678 break;
679 default: break;
681 aSdrCustomShapeInteraction.nMode = nMode;
682 xRet.push_back( aSdrCustomShapeInteraction );
687 catch( const uno::RuntimeException& )
690 return xRet;
694 // BaseProperties section
695 #define DEFAULT_MINIMUM_SIGNED_COMPARE ((sal_Int32)0x80000000)
696 #define DEFAULT_MAXIMUM_SIGNED_COMPARE ((sal_Int32)0x7fffffff)
698 static sal_Int32 GetNumberOfProperties ( const SvxMSDffHandle* pData )
700 sal_Int32 nPropertiesNeeded=1; // position is always needed
701 sal_Int32 nFlags = pData->nFlags;
703 if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X )
704 nPropertiesNeeded++;
705 if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y )
706 nPropertiesNeeded++;
707 if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED )
708 nPropertiesNeeded++;
709 if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR )
711 nPropertiesNeeded++;
712 if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE )
714 if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
715 nPropertiesNeeded++;
716 if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
717 nPropertiesNeeded++;
720 else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE )
722 if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
723 nPropertiesNeeded++;
724 if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
725 nPropertiesNeeded++;
726 if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
727 nPropertiesNeeded++;
728 if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
729 nPropertiesNeeded++;
732 return nPropertiesNeeded;
735 static void lcl_ShapePropertiesFromDFF( const SvxMSDffHandle* pData, com::sun::star::beans::PropertyValues& rPropValues )
737 sal_Int32 nFlags = pData->nFlags, n=0;
739 // POSITION
741 const OUString sPosition( "Position" );
742 ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition;
743 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, pData->nPositionX, true, true );
744 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, pData->nPositionY, true, false );
745 rPropValues[ n ].Name = sPosition;
746 rPropValues[ n++ ].Value <<= aPosition;
748 if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X )
750 const OUString sMirroredX( "MirroredX" );
751 bool bMirroredX = true;
752 rPropValues[ n ].Name = sMirroredX;
753 rPropValues[ n++ ].Value <<= bMirroredX;
755 if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y )
757 const OUString sMirroredY( "MirroredY" );
758 bool bMirroredY = true;
759 rPropValues[ n ].Name = sMirroredY;
760 rPropValues[ n++ ].Value <<= bMirroredY;
762 if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED )
764 const OUString sSwitched( "Switched" );
765 bool bSwitched = true;
766 rPropValues[ n ].Name = sSwitched;
767 rPropValues[ n++ ].Value <<= bSwitched;
769 if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR )
771 const OUString sPolar( "Polar" );
772 ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aCenter;
773 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.First, pData->nCenterX,
774 ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_X_IS_SPECIAL ) != 0, true );
775 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.Second, pData->nCenterY,
776 ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_Y_IS_SPECIAL ) != 0, false );
777 rPropValues[ n ].Name = sPolar;
778 rPropValues[ n++ ].Value <<= aCenter;
779 if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE )
781 if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
783 const OUString sRadiusRangeMinimum( "RadiusRangeMinimum" );
784 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
785 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, pData->nRangeXMin,
786 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, true );
787 rPropValues[ n ].Name = sRadiusRangeMinimum;
788 rPropValues[ n++ ].Value <<= aRadiusRangeMinimum;
790 if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
792 const OUString sRadiusRangeMaximum( "RadiusRangeMaximum" );
793 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
794 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, pData->nRangeXMax,
795 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, false );
796 rPropValues[ n ].Name = sRadiusRangeMaximum;
797 rPropValues[ n++ ].Value <<= aRadiusRangeMaximum;
801 else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE )
803 if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
805 const OUString sRangeXMinimum( "RangeXMinimum" );
806 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMinimum;
807 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, pData->nRangeXMin,
808 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, true );
809 rPropValues[ n ].Name = sRangeXMinimum;
810 rPropValues[ n++ ].Value <<= aRangeXMinimum;
812 if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
814 const OUString sRangeXMaximum( "RangeXMaximum" );
815 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMaximum;
816 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, pData->nRangeXMax,
817 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, false );
818 rPropValues[ n ].Name = sRangeXMaximum;
819 rPropValues[ n++ ].Value <<= aRangeXMaximum;
821 if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE )
823 const OUString sRangeYMinimum( "RangeYMinimum" );
824 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMinimum;
825 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, pData->nRangeYMin,
826 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MIN_IS_SPECIAL ) != 0, true );
827 rPropValues[ n ].Name = sRangeYMinimum;
828 rPropValues[ n++ ].Value <<= aRangeYMinimum;
830 if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE )
832 const OUString sRangeYMaximum( "RangeYMaximum" );
833 ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMaximum;
834 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, pData->nRangeYMax,
835 ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MAX_IS_SPECIAL ) != 0, false );
836 rPropValues[ n ].Name = sRangeYMaximum;
837 rPropValues[ n++ ].Value <<= aRangeYMaximum;
840 return;
843 sdr::properties::BaseProperties* SdrObjCustomShape::CreateObjectSpecificProperties()
845 return new sdr::properties::CustomShapeProperties(*this);
848 TYPEINIT1(SdrObjCustomShape,SdrTextObj);
849 SdrObjCustomShape::SdrObjCustomShape() :
850 SdrTextObj(),
851 fObjectRotation( 0.0 ),
852 mpLastShadowGeometry(0L)
854 bClosedObj = true; // custom shapes may be filled
855 bTextFrame = true;
858 SdrObjCustomShape::~SdrObjCustomShape()
860 // delete buffered display geometry
861 InvalidateRenderGeometry();
864 void SdrObjCustomShape::MergeDefaultAttributes( const OUString* pType )
866 PropertyValue aPropVal;
867 OUString sShapeType;
868 const OUString sType( "Type" );
869 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
870 if ( pType && !pType->isEmpty() )
872 sal_Int32 nType = pType->toInt32();
873 if ( nType )
874 sShapeType = EnhancedCustomShapeTypeNames::Get( static_cast< MSO_SPT >( nType ) );
875 else
876 sShapeType = *pType;
878 aPropVal.Name = sType;
879 aPropVal.Value <<= sShapeType;
880 aGeometryItem.SetPropertyValue( aPropVal );
882 else
884 Any *pAny = aGeometryItem.GetPropertyValueByName( sType );
885 if ( pAny )
886 *pAny >>= sShapeType;
888 MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
890 const sal_Int32* pDefData = NULL;
891 const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
892 if ( pDefCustomShape )
893 pDefData = pDefCustomShape->pDefData;
895 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > seqAdjustmentValues;
898 // AdjustmentValues
900 const OUString sAdjustmentValues( "AdjustmentValues" );
901 const Any* pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sAdjustmentValues );
902 if ( pAny )
903 *pAny >>= seqAdjustmentValues;
904 if ( pDefCustomShape && pDefData ) // now check if we have to default some adjustment values
906 // first check if there are adjustment values are to be appended
907 sal_Int32 i, nAdjustmentValues = seqAdjustmentValues.getLength();
908 sal_Int32 nAdjustmentDefaults = *pDefData++;
909 if ( nAdjustmentDefaults > nAdjustmentValues )
911 seqAdjustmentValues.realloc( nAdjustmentDefaults );
912 for ( i = nAdjustmentValues; i < nAdjustmentDefaults; i++ )
914 seqAdjustmentValues[ i ].Value <<= pDefData[ i ];
915 seqAdjustmentValues[ i ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
918 // check if there are defaulted adjustment values that should be filled the hard coded defaults (pDefValue)
919 sal_Int32 nCount = nAdjustmentValues > nAdjustmentDefaults ? nAdjustmentDefaults : nAdjustmentValues;
920 for ( i = 0; i < nCount; i++ )
922 if ( seqAdjustmentValues[ i ].State != com::sun::star::beans::PropertyState_DIRECT_VALUE )
924 seqAdjustmentValues[ i ].Value <<= pDefData[ i ];
925 seqAdjustmentValues[ i ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
929 aPropVal.Name = sAdjustmentValues;
930 aPropVal.Value <<= seqAdjustmentValues;
931 aGeometryItem.SetPropertyValue( aPropVal );
934 // Coordsize
936 const OUString sViewBox( "ViewBox" );
937 const Any* pViewBox = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sViewBox );
938 com::sun::star::awt::Rectangle aViewBox;
939 if ( !pViewBox || !(*pViewBox >>= aViewBox ) )
941 if ( pDefCustomShape )
943 aViewBox.X = 0;
944 aViewBox.Y = 0;
945 aViewBox.Width = pDefCustomShape->nCoordWidth;
946 aViewBox.Height= pDefCustomShape->nCoordHeight;
947 aPropVal.Name = sViewBox;
948 aPropVal.Value <<= aViewBox;
949 aGeometryItem.SetPropertyValue( aPropVal );
953 const OUString sPath( "Path" );
956 // Path/Coordinates
958 const OUString sCoordinates( "Coordinates" );
959 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sCoordinates );
960 if ( !pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices )
962 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates;
964 sal_Int32 i, nCount = pDefCustomShape->nVertices;
965 seqCoordinates.realloc( nCount );
966 for ( i = 0; i < nCount; i++ )
968 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates[ i ].First, pDefCustomShape->pVertices[ i ].nValA );
969 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates[ i ].Second, pDefCustomShape->pVertices[ i ].nValB );
971 aPropVal.Name = sCoordinates;
972 aPropVal.Value <<= seqCoordinates;
973 aGeometryItem.SetPropertyValue( sPath, aPropVal );
976 // Path/GluePoints
977 const OUString sGluePoints( "GluePoints" );
978 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sGluePoints );
979 if ( !pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints )
981 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqGluePoints;
982 sal_Int32 i, nCount = pDefCustomShape->nGluePoints;
983 seqGluePoints.realloc( nCount );
984 for ( i = 0; i < nCount; i++ )
986 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA );
987 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB );
989 aPropVal.Name = sGluePoints;
990 aPropVal.Value <<= seqGluePoints;
991 aGeometryItem.SetPropertyValue( sPath, aPropVal );
994 // Path/Segments
995 const OUString sSegments( "Segments" );
996 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sSegments );
997 if ( !pAny && pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements )
999 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments;
1001 sal_Int32 i, nCount = pDefCustomShape->nElements;
1002 seqSegments.realloc( nCount );
1003 for ( i = 0; i < nCount; i++ )
1005 EnhancedCustomShapeSegment& rSegInfo = seqSegments[ i ];
1006 sal_uInt16 nSDat = pDefCustomShape->pElements[ i ];
1007 lcl_ShapeSegmentFromBinary( rSegInfo, nSDat );
1009 aPropVal.Name = sSegments;
1010 aPropVal.Value <<= seqSegments;
1011 aGeometryItem.SetPropertyValue( sPath, aPropVal );
1014 // Path/StretchX
1015 const OUString sStretchX( "StretchX" );
1016 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchX );
1017 if ( !pAny && pDefCustomShape )
1019 sal_Int32 nXRef = pDefCustomShape->nXRef;
1020 if ( ( nXRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1022 aPropVal.Name = sStretchX;
1023 aPropVal.Value <<= nXRef;
1024 aGeometryItem.SetPropertyValue( sPath, aPropVal );
1028 // Path/StretchY
1029 const OUString sStretchY( "StretchY" );
1030 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchY );
1031 if ( !pAny && pDefCustomShape )
1033 sal_Int32 nYRef = pDefCustomShape->nYRef;
1034 if ( ( nYRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1036 aPropVal.Name = sStretchY;
1037 aPropVal.Value <<= nYRef;
1038 aGeometryItem.SetPropertyValue( sPath, aPropVal );
1042 // Path/TextFrames
1043 const OUString sTextFrames( "TextFrames" );
1044 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sTextFrames );
1045 if ( !pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect )
1047 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > seqTextFrames;
1049 sal_Int32 i, nCount = pDefCustomShape->nTextRect;
1050 seqTextFrames.realloc( nCount );
1051 const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect;
1052 for ( i = 0; i < nCount; i++, pRectangles++ )
1054 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].TopLeft.First, pRectangles->nPairA.nValA );
1055 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].TopLeft.Second, pRectangles->nPairA.nValB );
1056 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].BottomRight.First, pRectangles->nPairB.nValA );
1057 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].BottomRight.Second, pRectangles->nPairB.nValB );
1059 aPropVal.Name = sTextFrames;
1060 aPropVal.Value <<= seqTextFrames;
1061 aGeometryItem.SetPropertyValue( sPath, aPropVal );
1064 // Equations
1065 const OUString sEquations( "Equations" );
1066 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sEquations );
1067 if ( !pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation )
1069 com::sun::star::uno::Sequence< OUString > seqEquations;
1071 sal_Int32 i, nCount = pDefCustomShape->nCalculation;
1072 seqEquations.realloc( nCount );
1073 const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation;
1074 for ( i = 0; i < nCount; i++, pData++ )
1075 seqEquations[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] );
1076 aPropVal.Name = sEquations;
1077 aPropVal.Value <<= seqEquations;
1078 aGeometryItem.SetPropertyValue( aPropVal );
1081 // Handles
1082 const OUString sHandles( "Handles" );
1083 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sHandles );
1084 if ( !pAny && pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
1086 com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValues > seqHandles;
1088 sal_Int32 i, nCount = pDefCustomShape->nHandles;
1089 const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
1090 seqHandles.realloc( nCount );
1091 for ( i = 0; i < nCount; i++, pData++ )
1093 sal_Int32 nPropertiesNeeded;
1094 com::sun::star::beans::PropertyValues& rPropValues = seqHandles[ i ];
1095 nPropertiesNeeded = GetNumberOfProperties( pData );
1096 rPropValues.realloc( nPropertiesNeeded );
1097 lcl_ShapePropertiesFromDFF( pData, rPropValues );
1099 aPropVal.Name = sHandles;
1100 aPropVal.Value <<= seqHandles;
1101 aGeometryItem.SetPropertyValue( aPropVal );
1103 SetMergedItem( aGeometryItem );
1106 bool SdrObjCustomShape::IsDefaultGeometry( const DefaultType eDefaultType ) const
1108 bool bIsDefaultGeometry = false;
1110 PropertyValue aPropVal;
1111 OUString sShapeType;
1112 const OUString sType( "Type" );
1113 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
1115 Any *pAny = aGeometryItem.GetPropertyValueByName( sType );
1116 if ( pAny )
1117 *pAny >>= sShapeType;
1119 MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
1121 const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
1122 const OUString sPath( "Path" );
1123 switch( eDefaultType )
1125 case DEFAULT_VIEWBOX :
1127 const OUString sViewBox( "ViewBox" );
1128 const Any* pViewBox = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sViewBox );
1129 com::sun::star::awt::Rectangle aViewBox;
1130 if ( pViewBox && ( *pViewBox >>= aViewBox ) )
1132 if ( ( aViewBox.Width == pDefCustomShape->nCoordWidth )
1133 && ( aViewBox.Height == pDefCustomShape->nCoordHeight ) )
1134 bIsDefaultGeometry = true;
1137 break;
1139 case DEFAULT_PATH :
1141 const OUString sCoordinates( "Coordinates" );
1142 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sCoordinates );
1143 if ( pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices )
1145 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates1, seqCoordinates2;
1146 if ( *pAny >>= seqCoordinates1 )
1148 sal_Int32 i, nCount = pDefCustomShape->nVertices;
1149 seqCoordinates2.realloc( nCount );
1150 for ( i = 0; i < nCount; i++ )
1152 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ i ].First, pDefCustomShape->pVertices[ i ].nValA );
1153 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ i ].Second, pDefCustomShape->pVertices[ i ].nValB );
1155 if ( seqCoordinates1 == seqCoordinates2 )
1156 bIsDefaultGeometry = true;
1159 else if ( pDefCustomShape && ( ( pDefCustomShape->nVertices == 0 ) || ( pDefCustomShape->pVertices == 0 ) ) )
1160 bIsDefaultGeometry = true;
1162 break;
1164 case DEFAULT_GLUEPOINTS :
1166 const OUString sGluePoints( "GluePoints" );
1167 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sGluePoints );
1168 if ( pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints )
1170 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqGluePoints1, seqGluePoints2;
1171 if ( *pAny >>= seqGluePoints1 )
1173 sal_Int32 i, nCount = pDefCustomShape->nGluePoints;
1174 seqGluePoints2.realloc( nCount );
1175 for ( i = 0; i < nCount; i++ )
1177 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints2[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA );
1178 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints2[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB );
1180 if ( seqGluePoints1 == seqGluePoints2 )
1181 bIsDefaultGeometry = true;
1184 else if ( pDefCustomShape && ( pDefCustomShape->nGluePoints == 0 ) )
1185 bIsDefaultGeometry = true;
1187 break;
1189 case DEFAULT_SEGMENTS :
1191 // Path/Segments
1192 const OUString sSegments( "Segments" );
1193 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sSegments );
1194 if ( pAny )
1196 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments1, seqSegments2;
1197 if ( *pAny >>= seqSegments1 )
1199 if ( pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements )
1201 sal_Int32 i, nCount = pDefCustomShape->nElements;
1202 if ( nCount )
1204 seqSegments2.realloc( nCount );
1205 for ( i = 0; i < nCount; i++ )
1207 EnhancedCustomShapeSegment& rSegInfo = seqSegments2[ i ];
1208 sal_uInt16 nSDat = pDefCustomShape->pElements[ i ];
1209 lcl_ShapeSegmentFromBinary( rSegInfo, nSDat );
1211 if ( seqSegments1 == seqSegments2 )
1212 bIsDefaultGeometry = true;
1215 else
1217 // check if its the default segment description ( M L Z N )
1218 if ( seqSegments1.getLength() == 4 )
1220 if ( ( seqSegments1[ 0 ].Command == EnhancedCustomShapeSegmentCommand::MOVETO )
1221 && ( seqSegments1[ 1 ].Command == EnhancedCustomShapeSegmentCommand::LINETO )
1222 && ( seqSegments1[ 2 ].Command == EnhancedCustomShapeSegmentCommand::CLOSESUBPATH )
1223 && ( seqSegments1[ 3 ].Command == EnhancedCustomShapeSegmentCommand::ENDSUBPATH ) )
1224 bIsDefaultGeometry = true;
1229 else if ( pDefCustomShape && ( ( pDefCustomShape->nElements == 0 ) || ( pDefCustomShape->pElements == 0 ) ) )
1230 bIsDefaultGeometry = true;
1232 break;
1234 case DEFAULT_STRETCHX :
1236 const OUString sStretchX( "StretchX" );
1237 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchX );
1238 if ( pAny && pDefCustomShape )
1240 sal_Int32 nStretchX = 0;
1241 if ( *pAny >>= nStretchX )
1243 if ( pDefCustomShape->nXRef == nStretchX )
1244 bIsDefaultGeometry = true;
1247 else if ( pDefCustomShape && ( pDefCustomShape->nXRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1248 bIsDefaultGeometry = true;
1250 break;
1252 case DEFAULT_STRETCHY :
1254 const OUString sStretchY( "StretchY" );
1255 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchY );
1256 if ( pAny && pDefCustomShape )
1258 sal_Int32 nStretchY = 0;
1259 if ( *pAny >>= nStretchY )
1261 if ( pDefCustomShape->nYRef == nStretchY )
1262 bIsDefaultGeometry = true;
1265 else if ( pDefCustomShape && ( pDefCustomShape->nYRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) )
1266 bIsDefaultGeometry = true;
1268 break;
1270 case DEFAULT_EQUATIONS :
1272 const OUString sEquations( "Equations" );
1273 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sEquations );
1274 if ( pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation )
1276 com::sun::star::uno::Sequence< OUString > seqEquations1, seqEquations2;
1277 if ( *pAny >>= seqEquations1 )
1279 sal_Int32 i, nCount = pDefCustomShape->nCalculation;
1280 seqEquations2.realloc( nCount );
1282 const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation;
1283 for ( i = 0; i < nCount; i++, pData++ )
1284 seqEquations2[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] );
1286 if ( seqEquations1 == seqEquations2 )
1287 bIsDefaultGeometry = true;
1290 else if ( pDefCustomShape && ( ( pDefCustomShape->nCalculation == 0 ) || ( pDefCustomShape->pCalculation == 0 ) ) )
1291 bIsDefaultGeometry = true;
1293 break;
1295 case DEFAULT_TEXTFRAMES :
1297 const OUString sTextFrames( "TextFrames" );
1298 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sTextFrames );
1299 if ( pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect )
1301 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > seqTextFrames1, seqTextFrames2;
1302 if ( *pAny >>= seqTextFrames1 )
1304 sal_Int32 i, nCount = pDefCustomShape->nTextRect;
1305 seqTextFrames2.realloc( nCount );
1306 const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect;
1307 for ( i = 0; i < nCount; i++, pRectangles++ )
1309 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].TopLeft.First, pRectangles->nPairA.nValA );
1310 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].TopLeft.Second, pRectangles->nPairA.nValB );
1311 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].BottomRight.First, pRectangles->nPairB.nValA );
1312 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].BottomRight.Second, pRectangles->nPairB.nValB );
1314 if ( seqTextFrames1 == seqTextFrames2 )
1315 bIsDefaultGeometry = true;
1318 else if ( pDefCustomShape && ( ( pDefCustomShape->nTextRect == 0 ) || ( pDefCustomShape->pTextRect == 0 ) ) )
1319 bIsDefaultGeometry = true;
1321 break;
1323 case DEFAULT_HANDLES :
1325 const OUString sHandles( "Handles" );
1326 pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sHandles );
1327 if ( pAny && pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
1329 com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValues > seqHandles1, seqHandles2;
1330 if ( *pAny >>= seqHandles1 )
1332 sal_Int32 i, nCount = pDefCustomShape->nHandles;
1333 const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
1334 seqHandles2.realloc( nCount );
1335 for ( i = 0; i < nCount; i++, pData++ )
1337 sal_Int32 nPropertiesNeeded;
1338 com::sun::star::beans::PropertyValues& rPropValues = seqHandles2[ i ];
1339 nPropertiesNeeded = GetNumberOfProperties( pData );
1340 rPropValues.realloc( nPropertiesNeeded );
1341 lcl_ShapePropertiesFromDFF( pData, rPropValues );
1343 if ( seqHandles1 == seqHandles2 )
1344 bIsDefaultGeometry = true;
1347 else if ( pDefCustomShape && ( ( pDefCustomShape->nHandles == 0 ) || ( pDefCustomShape->pHandles == 0 ) ) )
1348 bIsDefaultGeometry = true;
1350 break;
1352 return bIsDefaultGeometry;
1355 void SdrObjCustomShape::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
1357 rInfo.bResizeFreeAllowed=fObjectRotation == 0.0;
1358 rInfo.bResizePropAllowed=true;
1359 rInfo.bRotateFreeAllowed=true;
1360 rInfo.bRotate90Allowed =true;
1361 rInfo.bMirrorFreeAllowed=true;
1362 rInfo.bMirror45Allowed =true;
1363 rInfo.bMirror90Allowed =true;
1364 rInfo.bTransparenceAllowed = false;
1365 rInfo.bGradientAllowed = false;
1366 rInfo.bShearAllowed =true;
1367 rInfo.bEdgeRadiusAllowed=false;
1368 rInfo.bNoContortion =true;
1370 // #i37011#
1371 if ( mXRenderedCustomShape.is() )
1373 const SdrObject* pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape );
1374 if ( pRenderedCustomShape )
1376 // #i37262#
1377 // Iterate self over the contained objects, since there are combinations of
1378 // polygon and curve objects. In that case, aInfo.bCanConvToPath and
1379 // aInfo.bCanConvToPoly would be false. What is needed here is an or, not an and.
1380 SdrObjListIter aIterator(*pRenderedCustomShape);
1381 while(aIterator.IsMore())
1383 SdrObject* pCandidate = aIterator.Next();
1384 SdrObjTransformInfoRec aInfo;
1385 pCandidate->TakeObjInfo(aInfo);
1387 // set path and poly conversion if one is possible since
1388 // this object will first be broken
1389 const bool bCanConvToPathOrPoly(aInfo.bCanConvToPath || aInfo.bCanConvToPoly);
1390 if(rInfo.bCanConvToPath != bCanConvToPathOrPoly)
1392 rInfo.bCanConvToPath = bCanConvToPathOrPoly;
1395 if(rInfo.bCanConvToPoly != bCanConvToPathOrPoly)
1397 rInfo.bCanConvToPoly = bCanConvToPathOrPoly;
1400 if(rInfo.bCanConvToContour != aInfo.bCanConvToContour)
1402 rInfo.bCanConvToContour = aInfo.bCanConvToContour;
1405 if(rInfo.bShearAllowed != aInfo.bShearAllowed)
1407 rInfo.bShearAllowed = aInfo.bShearAllowed;
1414 void SdrObjCustomShape::SetModel(SdrModel* pNewModel)
1416 SdrTextObj::SetModel(pNewModel);
1417 mXRenderedCustomShape.clear();
1420 sal_uInt16 SdrObjCustomShape::GetObjIdentifier() const
1422 return sal_uInt16(OBJ_CUSTOMSHAPE);
1427 void SdrObjCustomShape::RecalcSnapRect()
1429 SdrTextObj::RecalcSnapRect();
1431 const Rectangle& SdrObjCustomShape::GetSnapRect() const
1433 return SdrTextObj::GetSnapRect();
1435 const Rectangle& SdrObjCustomShape::GetCurrentBoundRect() const
1437 return SdrTextObj::GetCurrentBoundRect();
1439 const Rectangle& SdrObjCustomShape::GetLogicRect() const
1441 return SdrTextObj::GetLogicRect();
1444 // #115391# This implementation is based on the TextFrame size of the CustomShape and the
1445 // state of the ResizeShapeToFitText flag to correctly set TextMinFrameWidth/Height
1446 void SdrObjCustomShape::AdaptTextMinSize()
1448 if(!pModel || !pModel->IsPasteResize())
1450 const bool bResizeShapeToFitText(static_cast< const SdrTextAutoGrowHeightItem& >(GetObjectItem(SDRATTR_TEXT_AUTOGROWHEIGHT)).GetValue());
1451 SfxItemSet aSet(
1452 *GetObjectItemSet().GetPool(),
1453 SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT,
1454 SDRATTR_TEXT_MINFRAMEWIDTH, SDRATTR_TEXT_AUTOGROWWIDTH, // contains SDRATTR_TEXT_MAXFRAMEWIDTH
1455 0, 0);
1456 bool bChanged(false);
1458 if(bResizeShapeToFitText)
1460 // always reset MinWidthHeight to zero to only rely on text size and frame size
1461 // to allow resizing being completely dependent on text size only
1462 aSet.Put(SdrTextMinFrameWidthItem(0));
1463 aSet.Put(SdrTextMinFrameHeightItem(0));
1464 bChanged = true;
1466 else
1468 // recreate from CustomShape-specific TextBounds
1469 Rectangle aTextBound(aRect);
1471 if(GetTextBounds(aTextBound))
1473 const long nHDist(GetTextLeftDistance() + GetTextRightDistance());
1474 const long nVDist(GetTextUpperDistance() + GetTextLowerDistance());
1475 const long nTWdt(std::max(long(0), (long)(aTextBound.GetWidth() - 1 - nHDist)));
1476 const long nTHgt(std::max(long(0), (long)(aTextBound.GetHeight() - 1 - nVDist)));
1478 aSet.Put(SdrTextMinFrameWidthItem(nTWdt));
1479 aSet.Put(SdrTextMinFrameHeightItem(nTHgt));
1480 bChanged = true;
1484 if(bChanged)
1486 SetObjectItemSet(aSet);
1487 NbcAdjustTextFrameWidthAndHeight();
1492 void SdrObjCustomShape::NbcSetSnapRect( const Rectangle& rRect )
1494 aRect=rRect;
1495 ImpJustifyRect(aRect);
1496 InvalidateRenderGeometry();
1498 // #115391#
1499 AdaptTextMinSize();
1501 ImpCheckShear();
1502 SetRectsDirty();
1503 SetChanged();
1505 void SdrObjCustomShape::SetSnapRect( const Rectangle& rRect )
1507 Rectangle aBoundRect0;
1508 if ( pUserCall )
1509 aBoundRect0 = GetLastBoundRect();
1510 NbcSetSnapRect( rRect );
1511 BroadcastObjectChange();
1512 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
1514 void SdrObjCustomShape::NbcSetLogicRect( const Rectangle& rRect )
1516 aRect = rRect;
1517 ImpJustifyRect( aRect );
1518 InvalidateRenderGeometry();
1520 // #115391#
1521 AdaptTextMinSize();
1523 SetRectsDirty();
1524 SetChanged();
1526 void SdrObjCustomShape::SetLogicRect( const Rectangle& rRect )
1528 Rectangle aBoundRect0;
1529 if ( pUserCall )
1530 aBoundRect0 = GetLastBoundRect();
1531 NbcSetLogicRect(rRect);
1532 BroadcastObjectChange();
1533 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
1535 void SdrObjCustomShape::Move( const Size& rSiz )
1537 if ( rSiz.Width() || rSiz.Height() )
1539 Rectangle aBoundRect0;
1540 if ( pUserCall )
1541 aBoundRect0 = GetLastBoundRect();
1542 NbcMove(rSiz);
1543 SetChanged();
1544 BroadcastObjectChange();
1545 SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0);
1548 void SdrObjCustomShape::NbcMove( const Size& rSiz )
1550 SdrTextObj::NbcMove( rSiz );
1551 if ( mXRenderedCustomShape.is() )
1553 SdrObject* pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape );
1554 if ( pRenderedCustomShape )
1556 // #i97149# the visualisation shape needs to be informed
1557 // about change, too
1558 pRenderedCustomShape->ActionChanged();
1559 pRenderedCustomShape->NbcMove( rSiz );
1563 // #i37011# adapt geometry shadow
1564 if(mpLastShadowGeometry)
1566 mpLastShadowGeometry->NbcMove( rSiz );
1569 void SdrObjCustomShape::Resize( const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bUnsetRelative )
1571 SdrTextObj::Resize( rRef, xFact, yFact, bUnsetRelative );
1574 void SdrObjCustomShape::NbcResize( const Point& rRef, const Fraction& rxFact, const Fraction& ryFact )
1576 Fraction xFact( rxFact );
1577 Fraction yFact( ryFact );
1579 // taking care of handles that should not been changed
1580 Rectangle aOld( aRect );
1581 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
1583 SdrTextObj::NbcResize( rRef, xFact, yFact );
1585 if ( ( xFact.GetNumerator() != xFact.GetDenominator() )
1586 || ( yFact.GetNumerator()!= yFact.GetDenominator() ) )
1588 if ( ( ( xFact.GetNumerator() < 0 ) && ( xFact.GetDenominator() > 0 ) ) ||
1589 ( ( xFact.GetNumerator() > 0 ) && ( xFact.GetDenominator() < 0 ) ) )
1591 SetMirroredX( IsMirroredX() == false );
1593 if ( ( ( yFact.GetNumerator() < 0 ) && ( yFact.GetDenominator() > 0 ) ) ||
1594 ( ( yFact.GetNumerator() > 0 ) && ( yFact.GetDenominator() < 0 ) ) )
1596 SetMirroredY( IsMirroredY() == false );
1600 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd( aInteractionHandles.end() );
1601 aIter != aEnd; ++aIter )
1605 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
1606 aIter->xInteraction->setControllerPosition( aIter->aPosition );
1607 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X )
1609 sal_Int32 nX = ( aIter->aPosition.X - aOld.Left() ) + aRect.Left();
1610 aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( nX, aIter->xInteraction->getPosition().Y ) );
1612 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y )
1614 sal_Int32 nY = ( aIter->aPosition.Y - aOld.Top() ) + aRect.Top();
1615 aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( aIter->xInteraction->getPosition().X, nY ) );
1618 catch ( const uno::RuntimeException& )
1622 InvalidateRenderGeometry();
1624 void SdrObjCustomShape::NbcRotate( const Point& rRef, long nWink, double sn, double cs )
1626 bool bMirroredX = IsMirroredX();
1627 bool bMirroredY = IsMirroredY();
1629 fObjectRotation = fmod( fObjectRotation, 360.0 );
1630 if ( fObjectRotation < 0 )
1631 fObjectRotation = 360 + fObjectRotation;
1633 // the rotation angle for ashapes is stored in fObjectRotation, this rotation
1634 // has to be applied to the text object (which is internally using aGeo.nWink).
1635 SdrTextObj::NbcRotate( aRect.TopLeft(), -aGeo.nDrehWink, // retrieving the unrotated text object
1636 sin( (-aGeo.nDrehWink) * F_PI18000 ),
1637 cos( (-aGeo.nDrehWink) * F_PI18000 ) );
1638 aGeo.nDrehWink = 0; // resetting aGeo data
1639 aGeo.RecalcSinCos();
1641 long nW = (long)( fObjectRotation * 100 ); // applying our object rotation
1642 if ( bMirroredX )
1643 nW = 36000 - nW;
1644 if ( bMirroredY )
1645 nW = 18000 - nW;
1646 nW = nW % 36000;
1647 if ( nW < 0 )
1648 nW = 36000 + nW;
1649 SdrTextObj::NbcRotate( aRect.TopLeft(), nW, // applying text rotation
1650 sin( nW * F_PI18000 ),
1651 cos( nW * F_PI18000 ) );
1653 int nSwap = 0;
1654 if ( bMirroredX )
1655 nSwap ^= 1;
1656 if ( bMirroredY )
1657 nSwap ^= 1;
1659 double fWink = nWink; // updating to our new object rotation
1660 fWink /= 100.0;
1661 fObjectRotation = fmod( nSwap ? fObjectRotation - fWink : fObjectRotation + fWink, 360.0 );
1662 if ( fObjectRotation < 0 )
1663 fObjectRotation = 360 + fObjectRotation;
1665 SdrTextObj::NbcRotate( rRef, nWink, sn, cs ); // applying text rotation
1666 InvalidateRenderGeometry();
1669 void SdrObjCustomShape::NbcMirror( const Point& rRef1, const Point& rRef2 )
1671 // TTTT: Fix for old mirroring, can be removed again in aw080
1672 // storing horizontal and vertical flipping without modifying the rotate angle
1673 // decompose other flipping to rotation and MirrorX.
1674 long ndx = rRef2.X()-rRef1.X();
1675 long ndy = rRef2.Y()-rRef1.Y();
1677 if(!ndx) // MirroredX
1679 SetMirroredX(!IsMirroredX());
1680 SdrTextObj::NbcMirror( rRef1, rRef2 );
1682 else
1684 if(!ndy) // MirroredY
1686 SetMirroredY(!IsMirroredY());
1687 SdrTextObj::NbcMirror( rRef1, rRef2 );
1689 else // neither horizontal nor vertical
1691 SetMirroredX(!IsMirroredX());
1693 // call parent
1694 SdrTextObj::NbcMirror( rRef1, rRef2 );
1696 // update fObjectRotation
1697 long nTextObjRotation = aGeo.nDrehWink;
1698 double fWink = nTextObjRotation;
1700 fWink /= 100.0;
1702 bool bSingleFlip = (IsMirroredX()!= IsMirroredY());
1704 fObjectRotation = fmod( bSingleFlip ? -fWink : fWink, 360.0 );
1706 if ( fObjectRotation < 0 )
1708 fObjectRotation = 360.0 + fObjectRotation;
1713 InvalidateRenderGeometry();
1716 void SdrObjCustomShape::Shear( const Point& rRef, long nWink, double tn, bool bVShear )
1718 SdrTextObj::Shear( rRef, nWink, tn, bVShear );
1719 InvalidateRenderGeometry();
1721 void SdrObjCustomShape::NbcShear( const Point& rRef, long nWink, double tn, bool bVShear )
1723 // TTTT: Fix for old mirroring, can be removed again in aw080
1724 SdrTextObj::NbcShear(rRef,nWink,tn,bVShear);
1726 // updating fObjectRotation
1727 long nTextObjRotation = aGeo.nDrehWink;
1728 double fWink = nTextObjRotation;
1730 fWink /= 100.0;
1732 bool bSingleFlip = (IsMirroredX()!= IsMirroredY());
1734 fObjectRotation = fmod( bSingleFlip ? -fWink : fWink, 360.0 );
1736 if ( fObjectRotation < 0 )
1738 fObjectRotation = 360.0 + fObjectRotation;
1741 InvalidateRenderGeometry();
1746 SdrGluePoint SdrObjCustomShape::GetVertexGluePoint(sal_uInt16 nPosNum) const
1748 sal_Int32 nWdt = ImpGetLineWdt(); // #i25616#
1750 // #i25616#
1751 if(!LineIsOutsideGeometry())
1753 nWdt++;
1754 nWdt /= 2;
1757 Point aPt;
1758 switch (nPosNum) {
1759 case 0: aPt=aRect.TopCenter(); aPt.Y()-=nWdt; break;
1760 case 1: aPt=aRect.RightCenter(); aPt.X()+=nWdt; break;
1761 case 2: aPt=aRect.BottomCenter(); aPt.Y()+=nWdt; break;
1762 case 3: aPt=aRect.LeftCenter(); aPt.X()-=nWdt; break;
1764 if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan);
1765 if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1766 aPt-=GetSnapRect().Center();
1767 SdrGluePoint aGP(aPt);
1768 aGP.SetPercent(false);
1769 return aGP;
1774 // #i38892#
1775 void SdrObjCustomShape::ImpCheckCustomGluePointsAreAdded()
1777 const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
1779 if(pSdrObject)
1781 const SdrGluePointList* pSource = pSdrObject->GetGluePointList();
1783 if(pSource && pSource->GetCount())
1785 if(!SdrTextObj::GetGluePointList())
1787 SdrTextObj::ForceGluePointList();
1790 const SdrGluePointList* pList = SdrTextObj::GetGluePointList();
1792 if(pList)
1794 SdrGluePointList aNewList;
1795 sal_uInt16 a;
1797 for(a = 0; a < pSource->GetCount(); a++)
1799 SdrGluePoint aCopy((*pSource)[a]);
1800 aCopy.SetUserDefined(false);
1801 aNewList.Insert(aCopy);
1804 bool bMirroredX = IsMirroredX();
1805 bool bMirroredY = IsMirroredY();
1807 long nShearWink = aGeo.nShearWink;
1808 double fTan = aGeo.nTan;
1810 if ( aGeo.nDrehWink || nShearWink || bMirroredX || bMirroredY )
1812 Polygon aPoly( aRect );
1813 if( nShearWink )
1815 sal_uInt16 nPointCount=aPoly.GetSize();
1816 for (sal_uInt16 i=0; i<nPointCount; i++)
1817 ShearPoint(aPoly[i],aRect.Center(), fTan, false );
1819 if ( aGeo.nDrehWink )
1820 aPoly.Rotate( aRect.Center(), aGeo.nDrehWink / 10 );
1822 Rectangle aBoundRect( aPoly.GetBoundRect() );
1823 sal_Int32 nXDiff = aBoundRect.Left() - aRect.Left();
1824 sal_Int32 nYDiff = aBoundRect.Top() - aRect.Top();
1826 if (nShearWink&&((bMirroredX&&!bMirroredY)||(bMirroredY&&!bMirroredX)))
1828 nShearWink = -nShearWink;
1829 fTan = -fTan;
1832 Point aRef( aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
1833 for ( a = 0; a < aNewList.GetCount(); a++ )
1835 SdrGluePoint& rPoint = aNewList[ a ];
1836 Point aGlue( rPoint.GetPos() );
1837 if ( nShearWink )
1838 ShearPoint( aGlue, aRef, fTan );
1840 RotatePoint( aGlue, aRef, sin( fObjectRotation * F_PI180 ), cos( fObjectRotation * F_PI180 ) );
1841 if ( bMirroredX )
1842 aGlue.X() = aRect.GetWidth() - aGlue.X();
1843 if ( bMirroredY )
1844 aGlue.Y() = aRect.GetHeight() - aGlue.Y();
1845 aGlue.X() -= nXDiff;
1846 aGlue.Y() -= nYDiff;
1847 rPoint.SetPos( aGlue );
1851 for(a = 0; a < pList->GetCount(); a++)
1853 const SdrGluePoint& rCandidate = (*pList)[a];
1855 if(rCandidate.IsUserDefined())
1857 aNewList.Insert(rCandidate);
1861 // copy new list to local. This is NOT very convenient behavior, the local
1862 // GluePointList should not be set, but we delivered by using GetGluePointList(),
1863 // maybe on demand. Since the local object is changed here, this is assumed to
1864 // be a result of GetGluePointList and thus the list is copied
1865 if(pPlusData)
1867 pPlusData->SetGluePoints(aNewList);
1874 // #i38892#
1875 const SdrGluePointList* SdrObjCustomShape::GetGluePointList() const
1877 ((SdrObjCustomShape*)this)->ImpCheckCustomGluePointsAreAdded();
1878 return SdrTextObj::GetGluePointList();
1881 // #i38892#
1882 SdrGluePointList* SdrObjCustomShape::ForceGluePointList()
1884 if(SdrTextObj::ForceGluePointList())
1886 ImpCheckCustomGluePointsAreAdded();
1887 return SdrTextObj::ForceGluePointList();
1889 else
1891 return 0L;
1897 sal_uInt32 SdrObjCustomShape::GetHdlCount() const
1899 const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount());
1900 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
1901 return ( aInteractionHandles.size() + nBasicHdlCount );
1904 SdrHdl* SdrObjCustomShape::GetHdl( sal_uInt32 nHdlNum ) const
1906 SdrHdl* pH = NULL;
1907 const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount());
1909 if ( nHdlNum < nBasicHdlCount )
1910 pH = SdrTextObj::GetHdl( nHdlNum );
1911 else
1913 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
1914 const sal_uInt32 nCustomShapeHdlNum(nHdlNum - nBasicHdlCount);
1916 if ( nCustomShapeHdlNum < aInteractionHandles.size() )
1918 if ( aInteractionHandles[ nCustomShapeHdlNum ].xInteraction.is() )
1922 com::sun::star::awt::Point aPosition( aInteractionHandles[ nCustomShapeHdlNum ].xInteraction->getPosition() );
1923 pH = new SdrHdl( Point( aPosition.X, aPosition.Y ), HDL_CUSTOMSHAPE1 );
1924 pH->SetPointNum( nCustomShapeHdlNum );
1925 pH->SetObj( (SdrObject*)this );
1927 catch ( const uno::RuntimeException& )
1933 return pH;
1938 bool SdrObjCustomShape::hasSpecialDrag() const
1940 return true;
1943 bool SdrObjCustomShape::beginSpecialDrag(SdrDragStat& rDrag) const
1945 const SdrHdl* pHdl = rDrag.GetHdl();
1947 if(pHdl && HDL_CUSTOMSHAPE1 == pHdl->GetKind())
1949 rDrag.SetEndDragChangesAttributes(true);
1950 rDrag.SetNoSnap(true);
1952 else
1954 const SdrHdl* pHdl2 = rDrag.GetHdl();
1955 const SdrHdlKind eHdl((pHdl2 == NULL) ? HDL_MOVE : pHdl2->GetKind());
1957 switch( eHdl )
1959 case HDL_UPLFT :
1960 case HDL_UPPER :
1961 case HDL_UPRGT :
1962 case HDL_LEFT :
1963 case HDL_RIGHT :
1964 case HDL_LWLFT :
1965 case HDL_LOWER :
1966 case HDL_LWRGT :
1967 case HDL_MOVE :
1969 break;
1971 default:
1973 return false;
1978 return true;
1981 void SdrObjCustomShape::DragResizeCustomShape( const Rectangle& rNewRect, SdrObjCustomShape* pObj ) const
1983 Rectangle aOld( pObj->aRect );
1984 bool bOldMirroredX( pObj->IsMirroredX() );
1985 bool bOldMirroredY( pObj->IsMirroredY() );
1987 Rectangle aNewRect( rNewRect );
1988 aNewRect.Justify();
1990 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( pObj ) );
1992 GeoStat aGeoStat( pObj->GetGeoStat() );
1993 if ( aNewRect.TopLeft()!= pObj->aRect.TopLeft() &&
1994 ( pObj->aGeo.nDrehWink || pObj->aGeo.nShearWink ) )
1996 Point aNewPos( aNewRect.TopLeft() );
1997 if ( pObj->aGeo.nShearWink ) ShearPoint( aNewPos, aOld.TopLeft(), aGeoStat.nTan );
1998 if ( pObj->aGeo.nDrehWink ) RotatePoint(aNewPos, aOld.TopLeft(), aGeoStat.nSin, aGeoStat.nCos );
1999 aNewRect.SetPos( aNewPos );
2001 if ( aNewRect != pObj->aRect )
2003 pObj->SetLogicRect( aNewRect );
2004 pObj->InvalidateRenderGeometry();
2006 if ( rNewRect.Left() > rNewRect.Right() )
2008 Point aTop( ( pObj->GetSnapRect().Left() + pObj->GetSnapRect().Right() ) >> 1, pObj->GetSnapRect().Top() );
2009 Point aBottom( aTop.X(), aTop.Y() + 1000 );
2010 pObj->NbcMirror( aTop, aBottom );
2012 if ( rNewRect.Top() > rNewRect.Bottom() )
2014 Point aLeft( pObj->GetSnapRect().Left(), ( pObj->GetSnapRect().Top() + pObj->GetSnapRect().Bottom() ) >> 1 );
2015 Point aRight( aLeft.X() + 1000, aLeft.Y() );
2016 pObj->NbcMirror( aLeft, aRight );
2019 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd( aInteractionHandles.end() );
2020 aIter != aEnd ; ++aIter )
2024 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2025 aIter->xInteraction->setControllerPosition( aIter->aPosition );
2026 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X )
2028 sal_Int32 nX;
2029 if ( bOldMirroredX )
2031 nX = ( aIter->aPosition.X - aOld.Right() );
2032 if ( rNewRect.Left() > rNewRect.Right() )
2033 nX = pObj->aRect.Left() - nX;
2034 else
2035 nX += pObj->aRect.Right();
2037 else
2039 nX = ( aIter->aPosition.X - aOld.Left() );
2040 if ( rNewRect.Left() > rNewRect.Right() )
2041 nX = pObj->aRect.Right() - nX;
2042 else
2043 nX += pObj->aRect.Left();
2045 aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( nX, aIter->xInteraction->getPosition().Y ) );
2047 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y )
2049 sal_Int32 nY;
2050 if ( bOldMirroredY )
2052 nY = ( aIter->aPosition.Y - aOld.Bottom() );
2053 if ( rNewRect.Top() > rNewRect.Bottom() )
2054 nY = pObj->aRect.Top() - nY;
2055 else
2056 nY += pObj->aRect.Bottom();
2058 else
2060 nY = ( aIter->aPosition.Y - aOld.Top() );
2061 if ( rNewRect.Top() > rNewRect.Bottom() )
2062 nY = pObj->aRect.Bottom() - nY;
2063 else
2064 nY += pObj->aRect.Top();
2066 aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( aIter->xInteraction->getPosition().X, nY ) );
2069 catch ( const uno::RuntimeException& )
2076 void SdrObjCustomShape::DragMoveCustomShapeHdl( const Point aDestination, const sal_uInt16 nCustomShapeHdlNum, SdrObjCustomShape* pObj ) const
2078 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( pObj ) );
2079 if ( nCustomShapeHdlNum < aInteractionHandles.size() )
2081 SdrCustomShapeInteraction aInteractionHandle( aInteractionHandles[ nCustomShapeHdlNum ] );
2082 if ( aInteractionHandle.xInteraction.is() )
2086 com::sun::star::awt::Point aPt( aDestination.X(), aDestination.Y() );
2087 if ( aInteractionHandle.nMode & CUSTOMSHAPE_HANDLE_MOVE_SHAPE )
2089 sal_Int32 nXDiff = aPt.X - aInteractionHandle.aPosition.X;
2090 sal_Int32 nYDiff = aPt.Y - aInteractionHandle.aPosition.Y;
2092 pObj->aRect.Move( nXDiff, nYDiff );
2093 pObj->aOutRect.Move( nXDiff, nYDiff );
2094 pObj->maSnapRect.Move( nXDiff, nYDiff );
2095 pObj->SetRectsDirty(true);
2096 pObj->InvalidateRenderGeometry();
2098 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd( aInteractionHandles.end() ) ;
2099 aIter != aEnd; ++aIter)
2101 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2103 if ( aIter->xInteraction.is() )
2104 aIter->xInteraction->setControllerPosition( aIter->aPosition );
2108 aInteractionHandle.xInteraction->setControllerPosition( aPt );
2110 catch ( const uno::RuntimeException& )
2117 bool SdrObjCustomShape::applySpecialDrag(SdrDragStat& rDrag)
2119 const SdrHdl* pHdl = rDrag.GetHdl();
2120 const SdrHdlKind eHdl((pHdl == NULL) ? HDL_MOVE : pHdl->GetKind());
2122 switch(eHdl)
2124 case HDL_CUSTOMSHAPE1 :
2126 rDrag.SetEndDragChangesGeoAndAttributes(true);
2127 DragMoveCustomShapeHdl( rDrag.GetNow(), (sal_uInt16)pHdl->GetPointNum(), this );
2128 SetRectsDirty();
2129 InvalidateRenderGeometry();
2130 SetChanged();
2131 break;
2134 case HDL_UPLFT :
2135 case HDL_UPPER :
2136 case HDL_UPRGT :
2137 case HDL_LEFT :
2138 case HDL_RIGHT :
2139 case HDL_LWLFT :
2140 case HDL_LOWER :
2141 case HDL_LWRGT :
2143 DragResizeCustomShape(ImpDragCalcRect(rDrag), this);
2144 break;
2146 case HDL_MOVE :
2148 Move(Size(rDrag.GetDX(), rDrag.GetDY()));
2149 break;
2151 default: break;
2154 return true;
2159 void SdrObjCustomShape::DragCreateObject( SdrDragStat& rStat )
2161 Rectangle aRect1;
2162 rStat.TakeCreateRect( aRect1 );
2164 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
2166 sal_uInt32 nDefaultObjectSizeWidth = 3000; // default width from SDOptions ?
2167 sal_uInt32 nDefaultObjectSizeHeight= 3000;
2169 if ( ImpVerticalSwitch( *this ) )
2171 SetMirroredX( aRect1.Left() > aRect1.Right() );
2173 aRect1 = Rectangle( rStat.GetNow(), Size( nDefaultObjectSizeWidth, nDefaultObjectSizeHeight ) );
2174 // subtracting the horizontal difference of the latest handle from shape position
2175 if ( !aInteractionHandles.empty() )
2177 sal_Int32 nHandlePos = aInteractionHandles[ aInteractionHandles.size() - 1 ].xInteraction->getPosition().X;
2178 aRect1.Move( aRect.Left() - nHandlePos, 0 );
2181 ImpJustifyRect( aRect1 );
2182 rStat.SetActionRect( aRect1 );
2183 aRect = aRect1;
2184 SetRectsDirty();
2186 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd( aInteractionHandles.end() );
2187 aIter != aEnd ; ++aIter)
2191 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_CREATE_FIXED )
2192 aIter->xInteraction->setControllerPosition( awt::Point( rStat.GetStart().X(), rStat.GetStart().Y() ) );
2194 catch ( const uno::RuntimeException& )
2199 SetBoundRectDirty();
2200 bSnapRectDirty=true;
2203 bool SdrObjCustomShape::BegCreate( SdrDragStat& rDrag )
2205 return SdrTextObj::BegCreate( rDrag );
2208 bool SdrObjCustomShape::MovCreate(SdrDragStat& rStat)
2210 SdrView* pView = rStat.GetView(); // #i37448#
2211 if( pView && pView->IsSolidDragging() )
2213 InvalidateRenderGeometry();
2215 DragCreateObject( rStat );
2216 SetRectsDirty();
2217 return true;
2220 bool SdrObjCustomShape::EndCreate( SdrDragStat& rStat, SdrCreateCmd eCmd )
2222 DragCreateObject( rStat );
2224 // #115391#
2225 AdaptTextMinSize();
2227 SetRectsDirty();
2228 return ( eCmd == SDRCREATE_FORCEEND || rStat.GetPointAnz() >= 2 );
2231 basegfx::B2DPolyPolygon SdrObjCustomShape::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
2233 return GetLineGeometry( this, false );
2238 // in context with the SdrObjCustomShape the SdrTextAutoGrowHeightItem == true -> Resize Shape to fit text,
2239 // the SdrTextAutoGrowWidthItem == true -> Word wrap text in Shape
2240 bool SdrObjCustomShape::IsAutoGrowHeight() const
2242 const SfxItemSet& rSet = GetMergedItemSet();
2243 bool bIsAutoGrowHeight = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
2244 if ( bIsAutoGrowHeight && IsVerticalWriting() )
2245 bIsAutoGrowHeight = !((SdrTextWordWrapItem&)(rSet.Get(SDRATTR_TEXT_WORDWRAP))).GetValue();
2246 return bIsAutoGrowHeight;
2248 bool SdrObjCustomShape::IsAutoGrowWidth() const
2250 const SfxItemSet& rSet = GetMergedItemSet();
2251 bool bIsAutoGrowWidth = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
2252 if ( bIsAutoGrowWidth && !IsVerticalWriting() )
2253 bIsAutoGrowWidth = !((SdrTextWordWrapItem&)(rSet.Get(SDRATTR_TEXT_WORDWRAP))).GetValue();
2254 return bIsAutoGrowWidth;
2257 /* The following method is identical to the SdrTextObj::SetVerticalWriting method, the only difference
2258 is that the SdrAutoGrowWidthItem and SdrAutoGrowHeightItem are not exchanged if the vertical writing
2259 mode has been changed */
2261 void SdrObjCustomShape::SetVerticalWriting( bool bVertical )
2263 ForceOutlinerParaObject();
2265 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
2267 DBG_ASSERT( pOutlinerParaObject, "SdrTextObj::SetVerticalWriting() without OutlinerParaObject!" );
2269 if( pOutlinerParaObject )
2271 if(pOutlinerParaObject->IsVertical() != (bool)bVertical)
2273 // get item settings
2274 const SfxItemSet& rSet = GetObjectItemSet();
2276 // Also exchange horizontal and vertical adjust items
2277 SdrTextHorzAdjust eHorz = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue();
2278 SdrTextVertAdjust eVert = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
2280 // rescue object size
2281 Rectangle aObjectRect = GetSnapRect();
2283 // prepare ItemSet to set exchanged width and height items
2284 SfxItemSet aNewSet(*rSet.GetPool(),
2285 SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT,
2286 // Expanded item ranges to also support horizontal and vertical adjust.
2287 SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST,
2288 SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST,
2289 0, 0);
2291 aNewSet.Put(rSet);
2293 // Exchange horizontal and vertical adjusts
2294 switch(eVert)
2296 case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break;
2297 case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break;
2298 case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break;
2299 case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break;
2301 switch(eHorz)
2303 case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break;
2304 case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break;
2305 case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break;
2306 case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break;
2309 pOutlinerParaObject = GetOutlinerParaObject();
2310 if ( pOutlinerParaObject )
2311 pOutlinerParaObject->SetVertical(bVertical);
2312 SetObjectItemSet( aNewSet );
2314 // restore object size
2315 SetSnapRect(aObjectRect);
2319 bool SdrObjCustomShape::AdjustTextFrameWidthAndHeight(Rectangle& rR, bool bHgt, bool bWdt) const
2321 if ( pModel && HasText() && !rR.IsEmpty() )
2323 bool bWdtGrow=bWdt && IsAutoGrowWidth();
2324 bool bHgtGrow=bHgt && IsAutoGrowHeight();
2325 if ( bWdtGrow || bHgtGrow )
2327 Rectangle aR0(rR);
2328 long nHgt=0,nMinHgt=0,nMaxHgt=0;
2329 long nWdt=0,nMinWdt=0,nMaxWdt=0;
2330 Size aSiz(rR.GetSize()); aSiz.Width()--; aSiz.Height()--;
2331 Size aMaxSiz(100000,100000);
2332 Size aTmpSiz(pModel->GetMaxObjSize());
2333 if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width();
2334 if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height();
2335 if (bWdtGrow)
2337 nMinWdt=GetMinTextFrameWidth();
2338 nMaxWdt=GetMaxTextFrameWidth();
2339 if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width();
2340 if (nMinWdt<=0) nMinWdt=1;
2341 aSiz.Width()=nMaxWdt;
2343 if (bHgtGrow)
2345 nMinHgt=GetMinTextFrameHeight();
2346 nMaxHgt=GetMaxTextFrameHeight();
2347 if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height();
2348 if (nMinHgt<=0) nMinHgt=1;
2349 aSiz.Height()=nMaxHgt;
2351 long nHDist=GetTextLeftDistance()+GetTextRightDistance();
2352 long nVDist=GetTextUpperDistance()+GetTextLowerDistance();
2353 aSiz.Width()-=nHDist;
2354 aSiz.Height()-=nVDist;
2355 if ( aSiz.Width() < 2 )
2356 aSiz.Width() = 2; // minimum size=2
2357 if ( aSiz.Height() < 2 )
2358 aSiz.Height() = 2; // minimum size=2
2360 if(pEdtOutl)
2362 pEdtOutl->SetMaxAutoPaperSize( aSiz );
2363 if (bWdtGrow)
2365 Size aSiz2(pEdtOutl->CalcTextSize());
2366 nWdt=aSiz2.Width()+1; // a little more tolerance
2367 if (bHgtGrow) nHgt=aSiz2.Height()+1; // a little more tolerance
2368 } else
2370 nHgt=pEdtOutl->GetTextHeight()+1; // a little more tolerance
2373 else
2375 Outliner& rOutliner=ImpGetDrawOutliner();
2376 rOutliner.SetPaperSize(aSiz);
2377 rOutliner.SetUpdateMode(true);
2378 // TODO: add the optimization with bPortionInfoChecked again.
2379 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
2380 if( pOutlinerParaObject != NULL )
2382 rOutliner.SetText(*pOutlinerParaObject);
2383 rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
2385 if ( bWdtGrow )
2387 Size aSiz2(rOutliner.CalcTextSize());
2388 nWdt=aSiz2.Width()+1; // a little more tolerance
2389 if ( bHgtGrow )
2390 nHgt=aSiz2.Height()+1; // a little more tolerance
2392 else
2393 nHgt = rOutliner.GetTextHeight()+1; // a little more tolerance
2394 rOutliner.Clear();
2396 if ( nWdt < nMinWdt )
2397 nWdt = nMinWdt;
2398 if ( nWdt > nMaxWdt )
2399 nWdt = nMaxWdt;
2400 nWdt += nHDist;
2401 if ( nWdt < 1 )
2402 nWdt = 1; // nHDist may also be negative
2403 if ( nHgt < nMinHgt )
2404 nHgt = nMinHgt;
2405 if ( nHgt > nMaxHgt )
2406 nHgt = nMaxHgt;
2407 nHgt+=nVDist;
2408 if ( nHgt < 1 )
2409 nHgt = 1; // nVDist may also be negative
2410 long nWdtGrow = nWdt-(rR.Right()-rR.Left());
2411 long nHgtGrow = nHgt-(rR.Bottom()-rR.Top());
2412 if ( nWdtGrow == 0 )
2413 bWdtGrow = false;
2414 if ( nHgtGrow == 0 )
2415 bHgtGrow=false;
2416 if ( bWdtGrow || bHgtGrow )
2418 if ( bWdtGrow )
2420 SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
2421 if ( eHAdj == SDRTEXTHORZADJUST_LEFT )
2422 rR.Right()+=nWdtGrow;
2423 else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT )
2424 rR.Left()-=nWdtGrow;
2425 else
2427 long nWdtGrow2=nWdtGrow/2;
2428 rR.Left()-=nWdtGrow2;
2429 rR.Right()=rR.Left()+nWdt;
2432 if ( bHgtGrow )
2434 SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
2435 if ( eVAdj == SDRTEXTVERTADJUST_TOP )
2436 rR.Bottom()+=nHgtGrow;
2437 else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM )
2438 rR.Top()-=nHgtGrow;
2439 else
2441 long nHgtGrow2=nHgtGrow/2;
2442 rR.Top()-=nHgtGrow2;
2443 rR.Bottom()=rR.Top()+nHgt;
2446 if ( aGeo.nDrehWink )
2448 Point aD1(rR.TopLeft());
2449 aD1-=aR0.TopLeft();
2450 Point aD2(aD1);
2451 RotatePoint(aD2,Point(),aGeo.nSin,aGeo.nCos);
2452 aD2-=aD1;
2453 rR.Move(aD2.X(),aD2.Y());
2455 return true;
2459 return false;
2462 Rectangle SdrObjCustomShape::ImpCalculateTextFrame( const bool bHgt, const bool bWdt )
2464 Rectangle aReturnValue;
2466 Rectangle aOldTextRect( aRect ); // <- initial text rectangle
2468 Rectangle aNewTextRect( aRect ); // <- new text rectangle returned from the custom shape renderer,
2469 GetTextBounds( aNewTextRect ); // it depends to the current logical shape size
2471 Rectangle aAdjustedTextRect( aNewTextRect ); // <- new text rectangle is being tested by AdjustTextFrameWidthAndHeight to ensure
2472 if ( AdjustTextFrameWidthAndHeight( aAdjustedTextRect, bHgt, bWdt ) ) // that the new text rectangle is matching the current text size from the outliner
2474 if ( ( aAdjustedTextRect != aNewTextRect ) && ( aOldTextRect != aAdjustedTextRect ) )
2476 aReturnValue = aRect;
2477 double fXScale = (double)aOldTextRect.GetWidth() / (double)aNewTextRect.GetWidth();
2478 double fYScale = (double)aOldTextRect.GetHeight() / (double)aNewTextRect.GetHeight();
2479 double fRightDiff = (double)( aAdjustedTextRect.Right() - aNewTextRect.Right() ) * fXScale;
2480 double fLeftDiff = (double)( aAdjustedTextRect.Left() - aNewTextRect.Left() ) * fXScale;
2481 double fTopDiff = (double)( aAdjustedTextRect.Top() - aNewTextRect.Top() ) * fYScale;
2482 double fBottomDiff= (double)( aAdjustedTextRect.Bottom()- aNewTextRect.Bottom()) * fYScale;
2483 aReturnValue.Left() += (sal_Int32)fLeftDiff;
2484 aReturnValue.Right() += (sal_Int32)fRightDiff;
2485 aReturnValue.Top() += (sal_Int32)fTopDiff;
2486 aReturnValue.Bottom() += (sal_Int32)fBottomDiff;
2489 return aReturnValue;
2492 bool SdrObjCustomShape::NbcAdjustTextFrameWidthAndHeight(bool bHgt, bool bWdt)
2494 Rectangle aNewTextRect = ImpCalculateTextFrame( bHgt, bWdt );
2495 bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != aRect );
2496 if ( bRet )
2498 // taking care of handles that should not been changed
2499 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
2501 aRect = aNewTextRect;
2502 SetRectsDirty();
2503 SetChanged();
2505 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd ( aInteractionHandles.end() );
2506 aIter != aEnd ; ++aIter)
2510 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2511 aIter->xInteraction->setControllerPosition( aIter->aPosition );
2513 catch ( const uno::RuntimeException& )
2517 InvalidateRenderGeometry();
2519 return bRet;
2521 bool SdrObjCustomShape::AdjustTextFrameWidthAndHeight(bool bHgt, bool bWdt)
2523 Rectangle aNewTextRect = ImpCalculateTextFrame( bHgt, bWdt );
2524 bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != aRect );
2525 if ( bRet )
2527 Rectangle aBoundRect0;
2528 if ( pUserCall )
2529 aBoundRect0 = GetCurrentBoundRect();
2531 // taking care of handles that should not been changed
2532 std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) );
2534 aRect = aNewTextRect;
2535 SetRectsDirty();
2537 for (std::vector< SdrCustomShapeInteraction >::const_iterator aIter( aInteractionHandles.begin() ), aEnd( aInteractionHandles.end() ) ;
2538 aIter != aEnd ; ++aIter)
2542 if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED )
2543 aIter->xInteraction->setControllerPosition( aIter->aPosition );
2545 catch ( const uno::RuntimeException& )
2550 InvalidateRenderGeometry();
2551 SetChanged();
2552 BroadcastObjectChange();
2553 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
2555 return bRet;
2557 bool SdrObjCustomShape::BegTextEdit( SdrOutliner& rOutl )
2559 return SdrTextObj::BegTextEdit( rOutl );
2561 void SdrObjCustomShape::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const
2563 Size aPaperMin,aPaperMax;
2564 Rectangle aViewInit;
2565 TakeTextAnchorRect( aViewInit );
2566 if ( aGeo.nDrehWink )
2568 Point aCenter(aViewInit.Center());
2569 aCenter-=aViewInit.TopLeft();
2570 Point aCenter0(aCenter);
2571 RotatePoint(aCenter,Point(),aGeo.nSin,aGeo.nCos);
2572 aCenter-=aCenter0;
2573 aViewInit.Move(aCenter.X(),aCenter.Y());
2575 Size aAnkSiz(aViewInit.GetSize());
2576 aAnkSiz.Width()--; aAnkSiz.Height()--; // because GetSize() adds 1
2577 Size aMaxSiz(1000000,1000000);
2578 if (pModel!=NULL) {
2579 Size aTmpSiz(pModel->GetMaxObjSize());
2580 if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width();
2581 if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height();
2583 SdrTextHorzAdjust eHAdj(GetTextHorizontalAdjust());
2584 SdrTextVertAdjust eVAdj(GetTextVerticalAdjust());
2586 long nMinWdt = GetMinTextFrameWidth();
2587 long nMinHgt = GetMinTextFrameHeight();
2588 long nMaxWdt = GetMaxTextFrameWidth();
2589 long nMaxHgt = GetMaxTextFrameHeight();
2590 if (nMinWdt<1) nMinWdt=1;
2591 if (nMinHgt<1) nMinHgt=1;
2592 if ( nMaxWdt == 0 || nMaxWdt > aMaxSiz.Width() )
2593 nMaxWdt = aMaxSiz.Width();
2594 if ( nMaxHgt == 0 || nMaxHgt > aMaxSiz.Height() )
2595 nMaxHgt=aMaxSiz.Height();
2597 if (((SdrTextWordWrapItem&)(GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue())
2599 if ( IsVerticalWriting() )
2601 nMaxHgt = aAnkSiz.Height();
2602 nMinHgt = nMaxHgt;
2604 else
2606 nMaxWdt = aAnkSiz.Width();
2607 nMinWdt = nMaxWdt;
2610 aPaperMax.Width()=nMaxWdt;
2611 aPaperMax.Height()=nMaxHgt;
2613 aPaperMin.Width()=nMinWdt;
2614 aPaperMin.Height()=nMinHgt;
2616 if ( pViewMin )
2618 *pViewMin = aViewInit;
2620 long nXFree = aAnkSiz.Width() - aPaperMin.Width();
2621 if ( eHAdj == SDRTEXTHORZADJUST_LEFT )
2622 pViewMin->Right() -= nXFree;
2623 else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT )
2624 pViewMin->Left() += nXFree;
2625 else { pViewMin->Left() += nXFree / 2; pViewMin->Right() = pViewMin->Left() + aPaperMin.Width(); }
2627 long nYFree = aAnkSiz.Height() - aPaperMin.Height();
2628 if ( eVAdj == SDRTEXTVERTADJUST_TOP )
2629 pViewMin->Bottom() -= nYFree;
2630 else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM )
2631 pViewMin->Top() += nYFree;
2632 else { pViewMin->Top() += nYFree / 2; pViewMin->Bottom() = pViewMin->Top() + aPaperMin.Height(); }
2635 if( IsVerticalWriting() )
2636 aPaperMin.Width() = 0;
2637 else
2638 aPaperMin.Height() = 0;
2640 if( eHAdj != SDRTEXTHORZADJUST_BLOCK )
2641 aPaperMin.Width()=0;
2643 // For complete vertical adjust support, set paper min height to 0, here.
2644 if(SDRTEXTVERTADJUST_BLOCK != eVAdj )
2645 aPaperMin.Height() = 0;
2647 if (pPaperMin!=NULL) *pPaperMin=aPaperMin;
2648 if (pPaperMax!=NULL) *pPaperMax=aPaperMax;
2649 if (pViewInit!=NULL) *pViewInit=aViewInit;
2651 void SdrObjCustomShape::EndTextEdit( SdrOutliner& rOutl )
2653 SdrTextObj::EndTextEdit( rOutl );
2654 InvalidateRenderGeometry();
2656 void SdrObjCustomShape::TakeTextAnchorRect( Rectangle& rAnchorRect ) const
2658 if ( GetTextBounds( rAnchorRect ) )
2660 Point aRotateRef( maSnapRect.Center() );
2661 rAnchorRect.Left() += GetTextLeftDistance();
2662 rAnchorRect.Top() += GetTextUpperDistance();
2663 rAnchorRect.Right() -= GetTextRightDistance();
2664 rAnchorRect.Bottom() -= GetTextLowerDistance();
2665 ImpJustifyRect( rAnchorRect );
2667 if ( rAnchorRect.GetWidth() < 2 )
2668 rAnchorRect.Right() = rAnchorRect.Left() + 1; // minimal width is 2
2669 if ( rAnchorRect.GetHeight() < 2 )
2670 rAnchorRect.Bottom() = rAnchorRect.Top() + 1; // minimal height is 2
2671 if ( aGeo.nDrehWink )
2673 Point aP( rAnchorRect.TopLeft() );
2674 RotatePoint( aP, aRotateRef, aGeo.nSin, aGeo. nCos );
2675 rAnchorRect.SetPos( aP );
2678 else
2679 SdrTextObj::TakeTextAnchorRect( rAnchorRect );
2681 void SdrObjCustomShape::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, bool bNoEditText,
2682 Rectangle* pAnchorRect, bool /*bLineWidth*/) const
2684 Rectangle aAnkRect; // Rect in which we anchor
2685 TakeTextAnchorRect(aAnkRect);
2686 SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
2687 SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
2688 sal_uIntPtr nStat0=rOutliner.GetControlWord();
2689 Size aNullSize;
2691 rOutliner.SetControlWord(nStat0|EE_CNTRL_AUTOPAGESIZE);
2692 rOutliner.SetMinAutoPaperSize(aNullSize);
2693 sal_Int32 nMaxAutoPaperWidth = 1000000;
2694 sal_Int32 nMaxAutoPaperHeight= 1000000;
2696 long nAnkWdt=aAnkRect.GetWidth();
2697 long nAnkHgt=aAnkRect.GetHeight();
2699 if (((SdrTextWordWrapItem&)(GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue())
2701 if ( IsVerticalWriting() )
2702 nMaxAutoPaperHeight = nAnkHgt;
2703 else
2704 nMaxAutoPaperWidth = nAnkWdt;
2706 if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting())
2708 rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0));
2711 if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting())
2713 rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt));
2715 rOutliner.SetMaxAutoPaperSize( Size( nMaxAutoPaperWidth, nMaxAutoPaperHeight ) );
2716 rOutliner.SetPaperSize( aNullSize );
2718 // put text into the Outliner - if necessary the use the text from the EditOutliner
2719 OutlinerParaObject* pPara= GetOutlinerParaObject();
2720 if (pEdtOutl && !bNoEditText)
2721 pPara=pEdtOutl->CreateParaObject();
2723 if (pPara)
2725 bool bHitTest = false;
2726 if( pModel )
2727 bHitTest = &pModel->GetHitTestOutliner() == &rOutliner;
2729 const SdrTextObj* pTestObj = rOutliner.GetTextObj();
2730 if( !pTestObj || !bHitTest || pTestObj != this ||
2731 pTestObj->GetOutlinerParaObject() != GetOutlinerParaObject() )
2733 if( bHitTest )
2734 rOutliner.SetTextObj( this );
2736 rOutliner.SetUpdateMode(true);
2737 rOutliner.SetText(*pPara);
2740 else
2742 rOutliner.SetTextObj( NULL );
2744 if (pEdtOutl && !bNoEditText && pPara)
2745 delete pPara;
2747 rOutliner.SetUpdateMode(true);
2748 rOutliner.SetControlWord(nStat0);
2750 SdrText* pText = getActiveText();
2751 if( pText )
2752 pText->CheckPortionInfo( rOutliner );
2754 Point aTextPos(aAnkRect.TopLeft());
2755 Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() has a little added tolerance, no?
2757 // For draw objects containing text correct horizontal/vertical alignment if text is bigger
2758 // than the object itself. Without that correction, the text would always be
2759 // formatted to the left edge (or top edge when vertical) of the draw object.
2761 if( !IsTextFrame() )
2763 if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting())
2765 // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK,
2766 // else the alignment is wanted.
2767 if(SDRTEXTHORZADJUST_BLOCK == eHAdj)
2769 eHAdj = SDRTEXTHORZADJUST_CENTER;
2773 if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting())
2775 // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK,
2776 // else the alignment is wanted.
2777 if(SDRTEXTVERTADJUST_BLOCK == eVAdj)
2779 eVAdj = SDRTEXTVERTADJUST_CENTER;
2784 if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT)
2786 long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width();
2787 if (eHAdj==SDRTEXTHORZADJUST_CENTER)
2788 aTextPos.X()+=nFreeWdt/2;
2789 if (eHAdj==SDRTEXTHORZADJUST_RIGHT)
2790 aTextPos.X()+=nFreeWdt;
2792 if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM)
2794 long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height();
2795 if (eVAdj==SDRTEXTVERTADJUST_CENTER)
2796 aTextPos.Y()+=nFreeHgt/2;
2797 if (eVAdj==SDRTEXTVERTADJUST_BOTTOM)
2798 aTextPos.Y()+=nFreeHgt;
2800 if (aGeo.nDrehWink!=0)
2801 RotatePoint(aTextPos,aAnkRect.TopLeft(),aGeo.nSin,aGeo.nCos);
2803 if (pAnchorRect)
2804 *pAnchorRect=aAnkRect;
2806 // using rTextRect together with ContourFrame doesn't always work correctly
2807 rTextRect=Rectangle(aTextPos,aTextSiz);
2810 void SdrObjCustomShape::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject)
2812 SdrTextObj::NbcSetOutlinerParaObject( pTextObject );
2813 SetBoundRectDirty();
2814 SetRectsDirty(true);
2815 InvalidateRenderGeometry();
2818 SdrObjCustomShape* SdrObjCustomShape::Clone() const
2820 return CloneHelper< SdrObjCustomShape >();
2823 SdrObjCustomShape& SdrObjCustomShape::operator=(const SdrObjCustomShape& rObj)
2825 if( this == &rObj )
2826 return *this;
2827 SdrTextObj::operator=( rObj );
2828 aName = rObj.aName;
2829 fObjectRotation = rObj.fObjectRotation;
2830 InvalidateRenderGeometry();
2831 return *this;
2835 OUString SdrObjCustomShape::TakeObjNameSingul() const
2837 OUStringBuffer sName(ImpGetResStr(STR_ObjNameSingulCUSTOMSHAPE));
2838 OUString aNm(GetName());
2839 if (!aNm.isEmpty())
2841 sName.append(' ');
2842 sName.append('\'');
2843 sName.append(aNm);
2844 sName.append('\'');
2846 return sName.makeStringAndClear();
2849 OUString SdrObjCustomShape::TakeObjNamePlural() const
2851 return ImpGetResStr(STR_ObjNamePluralCUSTOMSHAPE);
2854 basegfx::B2DPolyPolygon SdrObjCustomShape::TakeXorPoly() const
2856 return GetLineGeometry( (SdrObjCustomShape*)this, false );
2859 basegfx::B2DPolyPolygon SdrObjCustomShape::TakeContour() const
2861 const SdrObject* pSdrObject = GetSdrObjectFromCustomShape();
2862 if ( pSdrObject )
2863 return pSdrObject->TakeContour();
2864 return basegfx::B2DPolyPolygon();
2867 SdrObject* SdrObjCustomShape::DoConvertToPolyObj(bool bBezier, bool bAddText) const
2869 // #i37011#
2870 SdrObject* pRetval = 0L;
2871 SdrObject* pRenderedCustomShape = 0L;
2873 if ( !mXRenderedCustomShape.is() )
2875 // force CustomShape
2876 ((SdrObjCustomShape*)this)->GetSdrObjectFromCustomShape();
2879 if ( mXRenderedCustomShape.is() )
2881 pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape );
2884 if ( pRenderedCustomShape )
2886 SdrObject* pCandidate = pRenderedCustomShape->Clone();
2887 DBG_ASSERT(pCandidate, "SdrObjCustomShape::DoConvertToPolyObj: Could not clone SdrObject (!)");
2888 pCandidate->SetModel(GetModel());
2889 pRetval = pCandidate->DoConvertToPolyObj(bBezier, bAddText);
2890 SdrObject::Free( pCandidate );
2892 if(pRetval)
2894 const bool bShadow(((SdrShadowItem&)GetMergedItem(SDRATTR_SHADOW)).GetValue());
2895 if(bShadow)
2897 pRetval->SetMergedItem(SdrShadowItem(true));
2901 if(bAddText && HasText() && !IsTextPath())
2903 pRetval = ImpConvertAddText(pRetval, bBezier);
2907 return pRetval;
2910 void SdrObjCustomShape::NbcSetStyleSheet( SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr )
2912 // #i40944#
2913 InvalidateRenderGeometry();
2914 SdrObject::NbcSetStyleSheet( pNewStyleSheet, bDontRemoveHardAttr );
2917 void SdrObjCustomShape::SetPage( SdrPage* pNewPage )
2919 SdrTextObj::SetPage( pNewPage );
2921 if( pNewPage )
2923 // invalidating rectangles by SetRectsDirty is not sufficient,
2924 // AdjustTextFrameWidthAndHeight() also has to be made, both
2925 // actions are done by NbcSetSnapRect
2926 Rectangle aTmp( aRect ); //creating temporary rectangle #i61108#
2927 NbcSetSnapRect( aTmp );
2931 SdrObjGeoData* SdrObjCustomShape::NewGeoData() const
2933 return new SdrAShapeObjGeoData;
2936 void SdrObjCustomShape::SaveGeoData(SdrObjGeoData& rGeo) const
2938 SdrTextObj::SaveGeoData( rGeo );
2939 SdrAShapeObjGeoData& rAGeo=(SdrAShapeObjGeoData&)rGeo;
2940 rAGeo.fObjectRotation = fObjectRotation;
2941 rAGeo.bMirroredX = IsMirroredX();
2942 rAGeo.bMirroredY = IsMirroredY();
2944 const OUString sAdjustmentValues( "AdjustmentValues" );
2945 Any* pAny( ( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ).GetPropertyValueByName( sAdjustmentValues ) );
2946 if ( pAny )
2947 *pAny >>= rAGeo.aAdjustmentSeq;
2950 void SdrObjCustomShape::RestGeoData(const SdrObjGeoData& rGeo)
2952 SdrTextObj::RestGeoData( rGeo );
2953 SdrAShapeObjGeoData& rAGeo=(SdrAShapeObjGeoData&)rGeo;
2954 fObjectRotation = rAGeo.fObjectRotation;
2955 SetMirroredX( rAGeo.bMirroredX );
2956 SetMirroredY( rAGeo.bMirroredY );
2958 SdrCustomShapeGeometryItem rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
2959 const OUString sAdjustmentValues( "AdjustmentValues" );
2960 PropertyValue aPropVal;
2961 aPropVal.Name = sAdjustmentValues;
2962 aPropVal.Value <<= rAGeo.aAdjustmentSeq;
2963 rGeometryItem.SetPropertyValue( aPropVal );
2964 SetMergedItem( rGeometryItem );
2966 InvalidateRenderGeometry();
2969 void SdrObjCustomShape::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
2971 // break up matrix
2972 basegfx::B2DTuple aScale;
2973 basegfx::B2DTuple aTranslate;
2974 double fRotate, fShearX;
2975 rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
2977 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
2978 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
2979 if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
2981 aScale.setX(fabs(aScale.getX()));
2982 aScale.setY(fabs(aScale.getY()));
2983 fRotate = fmod(fRotate + F_PI, F_2PI);
2986 // reset object shear and rotations
2987 aGeo.nDrehWink = 0;
2988 aGeo.RecalcSinCos();
2989 aGeo.nShearWink = 0;
2990 aGeo.RecalcTan();
2992 // force metric to pool metric
2993 const SfxMapUnit eMapUnit(GetObjectMapUnit());
2994 if(eMapUnit != SFX_MAPUNIT_100TH_MM)
2996 switch(eMapUnit)
2998 case SFX_MAPUNIT_TWIP :
3000 // position
3001 aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
3002 aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
3004 // size
3005 aScale.setX(ImplMMToTwips(aScale.getX()));
3006 aScale.setY(ImplMMToTwips(aScale.getY()));
3008 break;
3010 default:
3012 OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
3017 // if anchor is used, make position relative to it
3018 if( pModel && pModel->IsWriter() )
3020 if(GetAnchorPos().X() || GetAnchorPos().Y())
3022 aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3026 // build and set BaseRect (use scale)
3027 Point aPoint = Point();
3028 Size aSize(FRound(aScale.getX()), FRound(aScale.getY()));
3029 // fdo#47434 We need a valid rectangle here
3030 if( !aSize.Height() ) aSize.setHeight( 1 );
3031 if( !aSize.Width() ) aSize.setWidth( 1 );
3033 Rectangle aBaseRect(aPoint, aSize);
3034 SetSnapRect(aBaseRect);
3036 // shear?
3037 if(!basegfx::fTools::equalZero(fShearX))
3039 GeoStat aGeoStat;
3040 // #i123181# The fix for #121932# here was wrong, the trunk version does not correct the
3041 // mirrored shear values, neither at the object level, nor on the API or XML level. Taking
3042 // back the mirroring of the shear angle
3043 aGeoStat.nShearWink = FRound((atan(fShearX) / F_PI180) * 100.0);
3044 aGeoStat.RecalcTan();
3045 Shear(Point(), aGeoStat.nShearWink, aGeoStat.nTan, false);
3048 // rotation?
3049 if(!basegfx::fTools::equalZero(fRotate))
3051 GeoStat aGeoStat;
3053 // #i78696#
3054 // fRotate is mathematically correct, but aGeoStat.nDrehWink is
3055 // mirrored -> mirror value here
3056 aGeoStat.nDrehWink = NormAngle360(FRound(-fRotate / F_PI18000));
3057 aGeoStat.RecalcSinCos();
3058 Rotate(Point(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos);
3061 // translate?
3062 if(!aTranslate.equalZero())
3064 Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY())));
3068 // taking fObjectRotation instead of aGeo.nWink
3069 bool SdrObjCustomShape::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
3071 // get turn and shear
3072 double fRotate = fObjectRotation * F_PI180;
3073 double fShearX = (aGeo.nShearWink / 100.0) * F_PI180;
3075 // get aRect, this is the unrotated snaprect
3076 Rectangle aRectangle(aRect);
3078 bool bMirroredX = IsMirroredX();
3079 bool bMirroredY = IsMirroredY();
3080 if ( bMirroredX || bMirroredY )
3081 { // we have to retrieve the unmirrored rect
3083 GeoStat aNewGeo( aGeo );
3085 if ( bMirroredX )
3087 Polygon aPol( Rect2Poly( aRect, aNewGeo ) );
3088 Rectangle aBoundRect( aPol.GetBoundRect() );
3090 Point aRef1( ( aBoundRect.Left() + aBoundRect.Right() ) >> 1, aBoundRect.Top() );
3091 Point aRef2( aRef1.X(), aRef1.Y() + 1000 );
3092 sal_uInt16 i;
3093 sal_uInt16 nPntAnz=aPol.GetSize();
3094 for (i=0; i<nPntAnz; i++)
3096 MirrorPoint(aPol[i],aRef1,aRef2);
3098 // mirror polygon and move it a bit
3099 Polygon aPol0(aPol);
3100 aPol[0]=aPol0[1];
3101 aPol[1]=aPol0[0];
3102 aPol[2]=aPol0[3];
3103 aPol[3]=aPol0[2];
3104 aPol[4]=aPol0[1];
3105 Poly2Rect(aPol,aRectangle,aNewGeo);
3107 if ( bMirroredY )
3109 Polygon aPol( Rect2Poly( aRectangle, aNewGeo ) );
3110 Rectangle aBoundRect( aPol.GetBoundRect() );
3112 Point aRef1( aBoundRect.Left(), ( aBoundRect.Top() + aBoundRect.Bottom() ) >> 1 );
3113 Point aRef2( aRef1.X() + 1000, aRef1.Y() );
3114 sal_uInt16 i;
3115 sal_uInt16 nPntAnz=aPol.GetSize();
3116 for (i=0; i<nPntAnz; i++)
3118 MirrorPoint(aPol[i],aRef1,aRef2);
3120 // mirror polygon and move it a bit
3121 Polygon aPol0(aPol);
3122 aPol[0]=aPol0[1]; // This was WRONG for vertical (!)
3123 aPol[1]=aPol0[0]; // #i121932# Despite my own coment above
3124 aPol[2]=aPol0[3]; // it was *not* wrong even when the reordering
3125 aPol[3]=aPol0[2]; // *seems* to be specific for X-Mirrorings. Oh
3126 aPol[4]=aPol0[1]; // will I be happy when this old stuff is |gone| with aw080 (!)
3127 Poly2Rect(aPol,aRectangle,aNewGeo);
3131 // fill other values
3132 basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight());
3133 basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top());
3135 // position may be relative to anchorpos, convert
3136 if( pModel && pModel->IsWriter() )
3138 if(GetAnchorPos().X() || GetAnchorPos().Y())
3140 aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
3144 // force MapUnit to 100th mm
3145 const SfxMapUnit eMapUnit(GetObjectMapUnit());
3146 if(eMapUnit != SFX_MAPUNIT_100TH_MM)
3148 switch(eMapUnit)
3150 case SFX_MAPUNIT_TWIP :
3152 // position
3153 aTranslate.setX(ImplTwipsToMM(aTranslate.getX()));
3154 aTranslate.setY(ImplTwipsToMM(aTranslate.getY()));
3156 // size
3157 aScale.setX(ImplTwipsToMM(aScale.getX()));
3158 aScale.setY(ImplTwipsToMM(aScale.getY()));
3160 break;
3162 default:
3164 OSL_FAIL("TRGetBaseGeometry: Missing unit translation to 100th mm!");
3169 // build matrix
3170 rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
3171 aScale,
3172 basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX),
3173 basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate,
3174 aTranslate);
3176 return false;
3179 sdr::contact::ViewContact* SdrObjCustomShape::CreateObjectSpecificViewContact()
3181 return new sdr::contact::ViewContactOfSdrObjCustomShape(*this);
3184 // #i33136#
3185 bool SdrObjCustomShape::doConstructOrthogonal(const OUString& rName)
3187 bool bRetval(false);
3188 static OUString Imps_sNameASOrtho_quadrat( "quadrat" );
3189 static OUString Imps_sNameASOrtho_round_quadrat( "round-quadrat" );
3190 static OUString Imps_sNameASOrtho_circle( "circle" );
3191 static OUString Imps_sNameASOrtho_circle_pie( "circle-pie" );
3192 static OUString Imps_sNameASOrtho_ring( "ring" );
3194 if(Imps_sNameASOrtho_quadrat.equalsIgnoreAsciiCase(rName))
3196 bRetval = true;
3198 else if(Imps_sNameASOrtho_round_quadrat.equalsIgnoreAsciiCase(rName))
3200 bRetval = true;
3202 else if(Imps_sNameASOrtho_circle.equalsIgnoreAsciiCase(rName))
3204 bRetval = true;
3206 else if(Imps_sNameASOrtho_circle_pie.equalsIgnoreAsciiCase(rName))
3208 bRetval = true;
3210 else if(Imps_sNameASOrtho_ring.equalsIgnoreAsciiCase(rName))
3212 bRetval = true;
3215 return bRetval;
3218 // #i37011# centralize throw-away of render geometry
3219 void SdrObjCustomShape::InvalidateRenderGeometry()
3221 mXRenderedCustomShape = 0L;
3222 SdrObject::Free( mpLastShadowGeometry );
3223 mpLastShadowGeometry = 0L;
3226 void SdrObjCustomShape::impl_setUnoShape(const uno::Reference<uno::XInterface>& rxUnoShape)
3228 SdrTextObj::impl_setUnoShape(rxUnoShape);
3230 // The shape engine is created with _current_ shape. This means we
3231 // _must_ reset it when the shape changes.
3232 mxCustomShapeEngine.set(0);
3235 OUString SdrObjCustomShape::GetCustomShapeName()
3237 OUString sShapeName;
3238 OUString aEngine( ( (SdrCustomShapeEngineItem&)( *this ).GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ) ).GetValue() );
3239 if ( aEngine.isEmpty() || aEngine.equalsAscii( "com.sun.star.drawing.EnhancedCustomShapeEngine" ) )
3241 OUString sShapeType;
3242 const OUString sType("Type");
3243 SdrCustomShapeGeometryItem& rGeometryItem( (SdrCustomShapeGeometryItem&)( *this ).GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
3244 Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
3245 if ( pAny && ( *pAny >>= sShapeType ) )
3246 sShapeName = EnhancedCustomShapeTypeNames::GetAccName( sShapeType );
3248 return sShapeName;
3251 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */