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