diff options
Diffstat (limited to 'svx/source/svdraw/svdoashp.cxx')
-rw-r--r-- | svx/source/svdraw/svdoashp.cxx | 3504 |
1 files changed, 3504 insertions, 0 deletions
diff --git a/svx/source/svdraw/svdoashp.cxx b/svx/source/svdraw/svdoashp.cxx new file mode 100644 index 000000000000..6ab27c85aaf0 --- /dev/null +++ b/svx/source/svdraw/svdoashp.cxx @@ -0,0 +1,3504 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/svdoashp.hxx> +#include "unoapi.hxx" +#include <svx/unoshape.hxx> +#include <ucbhelper/content.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <unotools/datetime.hxx> +#include <sfx2/lnkbase.hxx> +#include <tools/urlobj.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/drawing/XCustomShapeEngine.hpp> +#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include "unopolyhelper.hxx" +#include <comphelper/processfactory.hxx> +#include <svl/urihelper.hxx> +#include <com/sun/star/uno/Sequence.h> +#include <svx/svdogrp.hxx> +#include <vcl/salbtype.hxx> // FRound +#include <svx/svddrag.hxx> +#include <svx/xpool.hxx> +#include <svx/xpoly.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include "svditer.hxx" +#include <svx/svdobj.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdetc.hxx> +#include <svx/svdattrx.hxx> // NotPersistItems +#include <svx/svdoedge.hxx> // #32383# Die Verbinder nach Move nochmal anbroadcasten +#include "svdglob.hxx" // StringCache +#include "svdstr.hrc" // Objektname +#include <editeng/eeitem.hxx> +#include "editeng/editstat.hxx" +#include <svx/svdoutl.hxx> +#include <editeng/outlobj.hxx> +#include <svx/sdtfchim.hxx> +#include "../customshapes/EnhancedCustomShapeGeometry.hxx" +#include "../customshapes/EnhancedCustomShapeTypeNames.hxx" +#include "../customshapes/EnhancedCustomShape2d.hxx" +#include <com/sun/star/beans/PropertyValues.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp> +#include <editeng/writingmodeitem.hxx> +#include <svx/xlnclit.hxx> +#include <svx/svxids.hrc> +#include <svl/whiter.hxx> +#include <svx/sdr/properties/customshapeproperties.hxx> +#include <svx/sdr/contact/viewcontactofsdrobjcustomshape.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlntrit.hxx> +#include <svx/xfltrit.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> +#include <vcl/bmpacc.hxx> +#include <svx/svdview.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +// #104018# replace macros above with type-safe methods +inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); } +inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); } + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::drawing; + +static MSO_SPT ImpGetCustomShapeType( const SdrObjCustomShape& rCustoShape ) +{ + MSO_SPT eRetValue = mso_sptNil; + + rtl::OUString aEngine( ( (SdrCustomShapeEngineItem&)rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ) ).GetValue() ); + if ( !aEngine.getLength() || aEngine.equalsAscii( "com.sun.star.drawing.EnhancedCustomShapeEngine" ) ) + { + rtl::OUString sShapeType; + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + SdrCustomShapeGeometryItem& rGeometryItem( (SdrCustomShapeGeometryItem&)rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + Any* pAny = rGeometryItem.GetPropertyValueByName( sType ); + if ( pAny && ( *pAny >>= sShapeType ) ) + eRetValue = EnhancedCustomShapeTypeNames::Get( sShapeType ); + } + return eRetValue; +}; + +static sal_Bool ImpVerticalSwitch( const SdrObjCustomShape& rCustoShape ) +{ + sal_Bool bRet = sal_False; + MSO_SPT eShapeType( ImpGetCustomShapeType( rCustoShape ) ); + switch( eShapeType ) + { + case mso_sptAccentBorderCallout90 : // 2 ortho + case mso_sptBorderCallout1 : // 2 diag + case mso_sptBorderCallout2 : // 3 + { + bRet = sal_True; + } + break; +/* + case mso_sptCallout1 : + case mso_sptAccentCallout1 : + case mso_sptAccentBorderCallout1 : + case mso_sptBorderCallout90 : + case mso_sptCallout90 : + case mso_sptAccentCallout90 : + case mso_sptCallout2 : + case mso_sptCallout3 : + case mso_sptAccentCallout2 : + case mso_sptAccentCallout3 : + case mso_sptBorderCallout3 : + case mso_sptAccentBorderCallout2 : + case mso_sptAccentBorderCallout3 : +*/ + default: break; + } + return bRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// #i37011# create a clone with all attributes changed to shadow attributes +// and translation executed, too. +SdrObject* ImpCreateShadowObjectClone(const SdrObject& rOriginal, const SfxItemSet& rOriginalSet) +{ + SdrObject* pRetval = 0L; + const sal_Bool bShadow(((SdrShadowItem&)rOriginalSet.Get(SDRATTR_SHADOW)).GetValue()); + + if(bShadow) + { + // create a shadow representing object + const sal_Int32 nXDist(((SdrShadowXDistItem&)(rOriginalSet.Get(SDRATTR_SHADOWXDIST))).GetValue()); + const sal_Int32 nYDist(((SdrShadowYDistItem&)(rOriginalSet.Get(SDRATTR_SHADOWYDIST))).GetValue()); + const ::Color aShadowColor(((SdrShadowColorItem&)(rOriginalSet.Get(SDRATTR_SHADOWCOLOR))).GetColorValue()); + const sal_uInt16 nShadowTransparence(((SdrShadowTransparenceItem&)(rOriginalSet.Get(SDRATTR_SHADOWTRANSPARENCE))).GetValue()); + pRetval = rOriginal.Clone(); + DBG_ASSERT(pRetval, "ImpCreateShadowObjectClone: Could not clone object (!)"); + + // look for used stuff + SdrObjListIter aIterator(rOriginal); + sal_Bool bLineUsed(sal_False); + sal_Bool bAllFillUsed(sal_False); + sal_Bool bSolidFillUsed(sal_False); + sal_Bool bGradientFillUsed(sal_False); + sal_Bool bHatchFillUsed(sal_False); + sal_Bool bBitmapFillUsed(sal_False); + + while(aIterator.IsMore()) + { + SdrObject* pObj = aIterator.Next(); + XFillStyle eFillStyle = ((XFillStyleItem&)(pObj->GetMergedItem(XATTR_FILLSTYLE))).GetValue(); + + if(!bLineUsed) + { + XLineStyle eLineStyle = ((XLineStyleItem&)(pObj->GetMergedItem(XATTR_LINESTYLE))).GetValue(); + + if(XLINE_NONE != eLineStyle) + { + bLineUsed = sal_True; + } + } + + if(!bAllFillUsed) + { + if(!bSolidFillUsed && XFILL_SOLID == eFillStyle) + { + bSolidFillUsed = sal_True; + bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed); + } + if(!bGradientFillUsed && XFILL_GRADIENT == eFillStyle) + { + bGradientFillUsed = sal_True; + bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed); + } + if(!bHatchFillUsed && XFILL_HATCH == eFillStyle) + { + bHatchFillUsed = sal_True; + bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed); + } + if(!bBitmapFillUsed && XFILL_BITMAP == eFillStyle) + { + bBitmapFillUsed = sal_True; + bAllFillUsed = (bSolidFillUsed || bGradientFillUsed || bHatchFillUsed || bBitmapFillUsed); + } + } + } + + // translate to shadow coordinates + pRetval->NbcMove(Size(nXDist, nYDist)); + + // set items as needed + SfxItemSet aTempSet(rOriginalSet); + + // SJ: #40108# :-( if a SvxWritingModeItem (Top->Bottom) is set the text object + // is creating a paraobject, but paraobjects can not be created without model. So + // we are preventing the crash by setting the writing mode always left to right, + // this is not bad since our shadow geometry does not contain text. + aTempSet.Put( SvxWritingModeItem( com::sun::star::text::WritingMode_LR_TB, SDRATTR_TEXTDIRECTION ) ); + + // no shadow + aTempSet.Put(SdrShadowItem(sal_False)); + aTempSet.Put(SdrShadowXDistItem(0L)); + aTempSet.Put(SdrShadowYDistItem(0L)); + + // line color and transparence like shadow + if(bLineUsed) + { + aTempSet.Put(XLineColorItem(String(), aShadowColor)); + aTempSet.Put(XLineTransparenceItem(nShadowTransparence)); + } + + // fill color and transparence like shadow + if(bSolidFillUsed) + { + aTempSet.Put(XFillColorItem(String(), aShadowColor)); + aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); + } + + // gradient and transparence like shadow + if(bGradientFillUsed) + { + XGradient aGradient(((XFillGradientItem&)(rOriginalSet.Get(XATTR_FILLGRADIENT))).GetGradientValue()); + sal_uInt8 nStartLuminance(aGradient.GetStartColor().GetLuminance()); + sal_uInt8 nEndLuminance(aGradient.GetEndColor().GetLuminance()); + + if(aGradient.GetStartIntens() != 100) + { + nStartLuminance = (sal_uInt8)(nStartLuminance * ((double)aGradient.GetStartIntens() / 100.0)); + } + + if(aGradient.GetEndIntens() != 100) + { + nEndLuminance = (sal_uInt8)(nEndLuminance * ((double)aGradient.GetEndIntens() / 100.0)); + } + + ::Color aStartColor( + (sal_uInt8)((nStartLuminance * aShadowColor.GetRed()) / 256), + (sal_uInt8)((nStartLuminance * aShadowColor.GetGreen()) / 256), + (sal_uInt8)((nStartLuminance * aShadowColor.GetBlue()) / 256)); + + ::Color aEndColor( + (sal_uInt8)((nEndLuminance * aShadowColor.GetRed()) / 256), + (sal_uInt8)((nEndLuminance * aShadowColor.GetGreen()) / 256), + (sal_uInt8)((nEndLuminance * aShadowColor.GetBlue()) / 256)); + + aGradient.SetStartColor(aStartColor); + aGradient.SetEndColor(aEndColor); + aTempSet.Put(XFillGradientItem(aTempSet.GetPool(), aGradient)); + aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); + } + + // hatch and transparence like shadow + if(bHatchFillUsed) + { + XHatch aHatch(((XFillHatchItem&)(rOriginalSet.Get(XATTR_FILLHATCH))).GetHatchValue()); + aHatch.SetColor(aShadowColor); + aTempSet.Put(XFillHatchItem(aTempSet.GetPool(), aHatch)); + aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); + } + + // bitmap and transparence like shadow + if(bBitmapFillUsed) + { + XOBitmap aFillBitmap(((XFillBitmapItem&)(rOriginalSet.Get(XATTR_FILLBITMAP))).GetBitmapValue()); + Bitmap aSourceBitmap(aFillBitmap.GetBitmap()); + BitmapReadAccess* pReadAccess = aSourceBitmap.AcquireReadAccess(); + + if(!aSourceBitmap.IsEmpty()) + { + if(pReadAccess) + { + Bitmap aDestBitmap(aSourceBitmap.GetSizePixel(), 24L); + BitmapWriteAccess* pWriteAccess = aDestBitmap.AcquireWriteAccess(); + + if(pWriteAccess) + { + for(sal_Int32 y(0L); y < pReadAccess->Height(); y++) + { + for(sal_Int32 x(0L); x < pReadAccess->Width(); x++) + { + sal_uInt16 nLuminance((sal_uInt16)pReadAccess->GetLuminance(y, x) + 1); + const BitmapColor aDestColor( + (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetRed()) >> 8L), + (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetGreen()) >> 8L), + (sal_uInt8)((nLuminance * (sal_uInt16)aShadowColor.GetBlue()) >> 8L)); + pWriteAccess->SetPixel(y, x, aDestColor); + } + } + + aDestBitmap.ReleaseAccess(pWriteAccess); + aFillBitmap.SetBitmap(aDestBitmap); + } + + aSourceBitmap.ReleaseAccess(pReadAccess); + } + } + + aTempSet.Put(XFillBitmapItem(aTempSet.GetPool(), aFillBitmap)); + aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); + } + + // set attributes and paint shadow object + pRetval->SetMergedItemSet( aTempSet ); + } + return pRetval; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Reference< XCustomShapeEngine > SdrObjCustomShape::GetCustomShapeEngine( const SdrObjCustomShape* pCustomShape ) +{ + Reference< XCustomShapeEngine > xCustomShapeEngine; + String aEngine(((SdrCustomShapeEngineItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE )).GetValue()); + if ( !aEngine.Len() ) + aEngine = String( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.drawing.EnhancedCustomShapeEngine" ) ); + + Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + + Reference< XShape > aXShape = GetXShapeForSdrObject( (SdrObjCustomShape*)pCustomShape ); + if ( aXShape.is() ) + { + if ( aEngine.Len() && xFactory.is() ) + { + Sequence< Any > aArgument( 1 ); + Sequence< PropertyValue > aPropValues( 1 ); + aPropValues[ 0 ].Name = rtl::OUString::createFromAscii( "CustomShape" ); + aPropValues[ 0 ].Value <<= aXShape; + aArgument[ 0 ] <<= aPropValues; + Reference< XInterface > xInterface( xFactory->createInstanceWithArguments( aEngine, aArgument ) ); + if ( xInterface.is() ) + xCustomShapeEngine = Reference< XCustomShapeEngine >( xInterface, UNO_QUERY ); + } + } + return xCustomShapeEngine; +} +const SdrObject* SdrObjCustomShape::GetSdrObjectFromCustomShape() const +{ + if ( !mXRenderedCustomShape.is() ) + { + Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( this ) ); + if ( xCustomShapeEngine.is() ) + ((SdrObjCustomShape*)this)->mXRenderedCustomShape = xCustomShapeEngine->render(); + } + SdrObject* pRenderedCustomShape = mXRenderedCustomShape.is() + ? GetSdrObjectFromXShape( mXRenderedCustomShape ) + : NULL; + return pRenderedCustomShape; +} + +// #i37011# Shadow geometry creation +const SdrObject* SdrObjCustomShape::GetSdrObjectShadowFromCustomShape() const +{ + if(!mpLastShadowGeometry) + { + const SdrObject* pSdrObject = GetSdrObjectFromCustomShape(); + if(pSdrObject) + { + const SfxItemSet& rOriginalSet = GetObjectItemSet(); + const sal_Bool bShadow(((SdrShadowItem&)rOriginalSet.Get( SDRATTR_SHADOW )).GetValue()); + + if(bShadow) + { + // create a clone with all attributes changed to shadow attributes + // and translation executed, too. + ((SdrObjCustomShape*)this)->mpLastShadowGeometry = ImpCreateShadowObjectClone(*pSdrObject, rOriginalSet); + } + } + } + + return mpLastShadowGeometry; +} + +sal_Bool SdrObjCustomShape::IsTextPath() const +{ + const rtl::OUString sTextPath( RTL_CONSTASCII_USTRINGPARAM ( "TextPath" ) ); + sal_Bool bTextPathOn = sal_False; + SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); + Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath ); + if ( pAny ) + *pAny >>= bTextPathOn; + return bTextPathOn; +} + +sal_Bool SdrObjCustomShape::UseNoFillStyle() const +{ + sal_Bool bRet = sal_False; + rtl::OUString sShapeType; + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + SdrCustomShapeGeometryItem& rGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + Any* pAny = rGeometryItem.GetPropertyValueByName( sType ); + if ( pAny ) + *pAny >>= sShapeType; + bRet = IsCustomShapeFilledByDefault( EnhancedCustomShapeTypeNames::Get( sType ) ) == 0; + + return bRet; +} + +sal_Bool SdrObjCustomShape::IsMirroredX() const +{ + sal_Bool bMirroredX = sal_False; + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX ); + if ( pAny ) + *pAny >>= bMirroredX; + return bMirroredX; +} +sal_Bool SdrObjCustomShape::IsMirroredY() const +{ + sal_Bool bMirroredY = sal_False; + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY ); + if ( pAny ) + *pAny >>= bMirroredY; + return bMirroredY; +} +void SdrObjCustomShape::SetMirroredX( const sal_Bool bMirrorX ) +{ + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + //com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX ); + PropertyValue aPropVal; + aPropVal.Name = sMirroredX; + aPropVal.Value <<= bMirrorX; + aGeometryItem.SetPropertyValue( aPropVal ); + SetMergedItem( aGeometryItem ); +} +void SdrObjCustomShape::SetMirroredY( const sal_Bool bMirrorY ) +{ + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + //com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY ); + PropertyValue aPropVal; + aPropVal.Name = sMirroredY; + aPropVal.Value <<= bMirrorY; + aGeometryItem.SetPropertyValue( aPropVal ); + SetMergedItem( aGeometryItem ); +} + +double SdrObjCustomShape::GetObjectRotation() const +{ + return fObjectRotation; +} + +double SdrObjCustomShape::GetExtraTextRotation() const +{ + const com::sun::star::uno::Any* pAny; + SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); + const rtl::OUString sTextRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) ); + pAny = rGeometryItem.GetPropertyValueByName( sTextRotateAngle ); + double fExtraTextRotateAngle = 0.0; + if ( pAny ) + *pAny >>= fExtraTextRotateAngle; + return fExtraTextRotateAngle; +} +sal_Bool SdrObjCustomShape::GetTextBounds( Rectangle& rTextBound ) const +{ + sal_Bool bRet = sal_False; + Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( this ) ); // a candidate for being cached + if ( xCustomShapeEngine.is() ) + { + awt::Rectangle aR( xCustomShapeEngine->getTextBounds() ); + if ( aR.Width || aR.Height ) + { + rTextBound = Rectangle( Point( aR.X, aR.Y ), Size( aR.Width, aR.Height ) ); + bRet = sal_True; + } + } + return bRet; +} +basegfx::B2DPolyPolygon SdrObjCustomShape::GetLineGeometry( const SdrObjCustomShape* pCustomShape, const sal_Bool bBezierAllowed ) +{ + basegfx::B2DPolyPolygon aRetval; + sal_Bool bRet = sal_False; + Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( pCustomShape ) ); + if ( xCustomShapeEngine.is() ) + { + com::sun::star::drawing::PolyPolygonBezierCoords aBezierCoords = xCustomShapeEngine->getLineGeometry(); + try + { + aRetval = SvxConvertPolyPolygonBezierToB2DPolyPolygon( &aBezierCoords ); + if ( !bBezierAllowed && aRetval.areControlPointsUsed()) + { + aRetval = basegfx::tools::adaptiveSubdivideByAngle(aRetval); + } + bRet = sal_True; + } + catch ( const com::sun::star::lang::IllegalArgumentException ) + { + } + } + return aRetval; +} + +std::vector< SdrCustomShapeInteraction > SdrObjCustomShape::GetInteractionHandles( const SdrObjCustomShape* pCustomShape ) const +{ + std::vector< SdrCustomShapeInteraction > xRet; + try + { + Reference< XCustomShapeEngine > xCustomShapeEngine( GetCustomShapeEngine( pCustomShape ) ); + if ( xCustomShapeEngine.is() ) + { + int i; + Sequence< Reference< XCustomShapeHandle > > xInteractionHandles( xCustomShapeEngine->getInteraction() ); + for ( i = 0; i < xInteractionHandles.getLength(); i++ ) + { + if ( xInteractionHandles[ i ].is() ) + { + SdrCustomShapeInteraction aSdrCustomShapeInteraction; + aSdrCustomShapeInteraction.xInteraction = xInteractionHandles[ i ]; + aSdrCustomShapeInteraction.aPosition = xInteractionHandles[ i ]->getPosition(); + + sal_Int32 nMode = 0; + switch( ImpGetCustomShapeType( *this ) ) + { + case mso_sptAccentBorderCallout90 : // 2 ortho + { + if ( !i ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED; + else if ( i == 1) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE | CUSTOMSHAPE_HANDLE_ORTHO4; + } + break; + + case mso_sptWedgeRectCallout : + case mso_sptWedgeRRectCallout : + case mso_sptCloudCallout : + case mso_sptWedgeEllipseCallout : + { + if ( !i ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED; + } + break; + + case mso_sptBorderCallout1 : // 2 diag + { + if ( !i ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED; + else if ( i == 1 ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE; + } + break; + case mso_sptBorderCallout2 : // 3 + { + if ( !i ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED; + else if ( i == 2 ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X | CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y | CUSTOMSHAPE_HANDLE_MOVE_SHAPE; + } + break; + case mso_sptCallout90 : + case mso_sptAccentCallout90 : + case mso_sptBorderCallout90 : + case mso_sptCallout1 : + case mso_sptCallout2 : + case mso_sptCallout3 : + case mso_sptAccentCallout1 : + case mso_sptAccentCallout2 : + case mso_sptAccentCallout3 : + case mso_sptBorderCallout3 : + case mso_sptAccentBorderCallout1 : + case mso_sptAccentBorderCallout2 : + case mso_sptAccentBorderCallout3 : + { + if ( !i ) + nMode |= CUSTOMSHAPE_HANDLE_RESIZE_FIXED | CUSTOMSHAPE_HANDLE_CREATE_FIXED; + } + break; + default: break; + } + aSdrCustomShapeInteraction.nMode = nMode; + xRet.push_back( aSdrCustomShapeInteraction ); + } + } + } + } + catch( const uno::RuntimeException& ) + { + } + return xRet; +} + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section +#define DEFAULT_MINIMUM_SIGNED_COMPARE ((sal_Int32)0x80000000) +#define DEFAULT_MAXIMUM_SIGNED_COMPARE ((sal_Int32)0x7fffffff) + +sdr::properties::BaseProperties* SdrObjCustomShape::CreateObjectSpecificProperties() +{ + return new sdr::properties::CustomShapeProperties(*this); +} + +TYPEINIT1(SdrObjCustomShape,SdrTextObj); +SdrObjCustomShape::SdrObjCustomShape() : + SdrTextObj(), + fObjectRotation( 0.0 ), + mpLastShadowGeometry(0L) +{ + bTextFrame = TRUE; +} + +SdrObjCustomShape::~SdrObjCustomShape() +{ + // delete buffered display geometry + InvalidateRenderGeometry(); +} + +void SdrObjCustomShape::MergeDefaultAttributes( const rtl::OUString* pType ) +{ + PropertyValue aPropVal; + rtl::OUString sShapeType; + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + if ( pType && pType->getLength() ) + { + sal_Int32 nType = pType->toInt32(); + if ( nType ) + sShapeType = EnhancedCustomShapeTypeNames::Get( static_cast< MSO_SPT >( nType ) ); + else + sShapeType = *pType; + + aPropVal.Name = sType; + aPropVal.Value <<= sShapeType; + aGeometryItem.SetPropertyValue( aPropVal ); + } + else + { + Any *pAny = aGeometryItem.GetPropertyValueByName( sType ); + if ( pAny ) + *pAny >>= sShapeType; + } + MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType ); + + const sal_Int32* pDefData = NULL; + const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType ); + if ( pDefCustomShape ) + pDefData = pDefCustomShape->pDefData; + + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > seqAdjustmentValues; + + ////////////////////// + // AdjustmentValues // + ////////////////////// + const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) ); + const Any* pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sAdjustmentValues ); + if ( pAny ) + *pAny >>= seqAdjustmentValues; + if ( pDefCustomShape && pDefData ) // now check if we have to default some adjustment values + { + // first check if there are adjustment values are to be appended + sal_Int32 i, nAdjustmentValues = seqAdjustmentValues.getLength(); + sal_Int32 nAdjustmentDefaults = *pDefData++; + if ( nAdjustmentDefaults > nAdjustmentValues ) + { + seqAdjustmentValues.realloc( nAdjustmentDefaults ); + for ( i = nAdjustmentValues; i < nAdjustmentDefaults; i++ ) + { + seqAdjustmentValues[ i ].Value <<= pDefData[ i ]; + seqAdjustmentValues[ i ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE; // com::sun::star::beans::PropertyState_DEFAULT_VALUE; + } + } + // check if there are defaulted adjustment values that should be filled the hard coded defaults (pDefValue) + sal_Int32 nCount = nAdjustmentValues > nAdjustmentDefaults ? nAdjustmentDefaults : nAdjustmentValues; + for ( i = 0; i < nCount; i++ ) + { + if ( seqAdjustmentValues[ i ].State != com::sun::star::beans::PropertyState_DIRECT_VALUE ) + { + seqAdjustmentValues[ i ].Value <<= pDefData[ i ]; + seqAdjustmentValues[ i ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE; + } + } + } + aPropVal.Name = sAdjustmentValues; + aPropVal.Value <<= seqAdjustmentValues; + aGeometryItem.SetPropertyValue( aPropVal ); + + /////////////// + // Coordsize // + /////////////// + const rtl::OUString sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) ); + const Any* pViewBox = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sViewBox ); + com::sun::star::awt::Rectangle aViewBox; + if ( !pViewBox || !(*pViewBox >>= aViewBox ) ) + { + if ( pDefCustomShape ) + { + aViewBox.X = 0; + aViewBox.Y = 0; + aViewBox.Width = pDefCustomShape->nCoordWidth; + aViewBox.Height= pDefCustomShape->nCoordHeight; + aPropVal.Name = sViewBox; + aPropVal.Value <<= aViewBox; + aGeometryItem.SetPropertyValue( aPropVal ); + } + } + + const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM ( "Path" ) ); + + ////////////////////// + // Path/Coordinates // + ////////////////////// + const rtl::OUString sCoordinates( RTL_CONSTASCII_USTRINGPARAM ( "Coordinates" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sCoordinates ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates; + + sal_Int32 i, nCount = pDefCustomShape->nVertices; + seqCoordinates.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates[ i ].First, pDefCustomShape->pVertices[ i ].nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates[ i ].Second, pDefCustomShape->pVertices[ i ].nValB ); + } + aPropVal.Name = sCoordinates; + aPropVal.Value <<= seqCoordinates; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + + ///////////////////// + // Path/GluePoints // + ///////////////////// + const rtl::OUString sGluePoints( RTL_CONSTASCII_USTRINGPARAM ( "GluePoints" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sGluePoints ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqGluePoints; + sal_Int32 i, nCount = pDefCustomShape->nGluePoints; + seqGluePoints.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB ); + } + aPropVal.Name = sGluePoints; + aPropVal.Value <<= seqGluePoints; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + + /////////////////// + // Path/Segments // + /////////////////// + const rtl::OUString sSegments( RTL_CONSTASCII_USTRINGPARAM ( "Segments" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sSegments ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments; + + sal_Int32 i, nCount = pDefCustomShape->nElements; + seqSegments.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShapeSegment& rSegInfo = seqSegments[ i ]; + sal_uInt16 nSDat = pDefCustomShape->pElements[ i ]; + switch( nSDat >> 8 ) + { + case 0x00 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::LINETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x20 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CURVETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x40 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::MOVETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x60 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH; + rSegInfo.Count = 0; + } + break; + case 0x80 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ENDSUBPATH; + rSegInfo.Count = 0; + } + break; + case 0xa1 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO; + rSegInfo.Count = ( nSDat & 0xff ) / 3; + } + break; + case 0xa2 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE; + rSegInfo.Count = ( nSDat & 0xff ) / 3; + } + break; + case 0xa3 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARCTO; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa4 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARC; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa5 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa6 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa7 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX; + rSegInfo.Count = nSDat & 0xff; + } + break; + case 0xa8 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY; + rSegInfo.Count = nSDat & 0xff; + } + break; + case 0xaa : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOFILL; + rSegInfo.Count = 0; + } + break; + case 0xab : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOSTROKE; + rSegInfo.Count = 0; + } + break; + default: + case 0xf8 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::UNKNOWN; + rSegInfo.Count = nSDat; + } + break; + } + } + aPropVal.Name = sSegments; + aPropVal.Value <<= seqSegments; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + + /////////////////// + // Path/StretchX // + /////////////////// + const rtl::OUString sStretchX( RTL_CONSTASCII_USTRINGPARAM ( "StretchX" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchX ); + if ( !pAny && pDefCustomShape ) + { + sal_Int32 nXRef = pDefCustomShape->nXRef; + if ( ( nXRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) ) + { + aPropVal.Name = sStretchX; + aPropVal.Value <<= nXRef; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + } + + /////////////////// + // Path/StretchY // + /////////////////// + const rtl::OUString sStretchY( RTL_CONSTASCII_USTRINGPARAM ( "StretchY" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchY ); + if ( !pAny && pDefCustomShape ) + { + sal_Int32 nYRef = pDefCustomShape->nYRef; + if ( ( nYRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) ) + { + aPropVal.Name = sStretchY; + aPropVal.Value <<= nYRef; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + } + + ///////////////////// + // Path/TextFrames // + ///////////////////// + const rtl::OUString sTextFrames( RTL_CONSTASCII_USTRINGPARAM ( "TextFrames" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sTextFrames ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > seqTextFrames; + + sal_Int32 i, nCount = pDefCustomShape->nTextRect; + seqTextFrames.realloc( nCount ); + const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect; + for ( i = 0; i < nCount; i++, pRectangles++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].TopLeft.First, pRectangles->nPairA.nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].TopLeft.Second, pRectangles->nPairA.nValB ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].BottomRight.First, pRectangles->nPairB.nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames[ i ].BottomRight.Second, pRectangles->nPairB.nValB ); + } + aPropVal.Name = sTextFrames; + aPropVal.Value <<= seqTextFrames; + aGeometryItem.SetPropertyValue( sPath, aPropVal ); + } + + /////////////// + // Equations // + /////////////// + const rtl::OUString sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sEquations ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation ) + { + com::sun::star::uno::Sequence< rtl::OUString > seqEquations; + + sal_Int32 i, nCount = pDefCustomShape->nCalculation; + seqEquations.realloc( nCount ); + const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation; + for ( i = 0; i < nCount; i++, pData++ ) + seqEquations[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] ); + aPropVal.Name = sEquations; + aPropVal.Value <<= seqEquations; + aGeometryItem.SetPropertyValue( aPropVal ); + } + + ///////////// + // Handles // + ///////////// + const rtl::OUString sHandles( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sHandles ); + if ( !pAny && pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles ) + { + com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValues > seqHandles; + + sal_Int32 i, n, nCount = pDefCustomShape->nHandles; + const SvxMSDffHandle* pData = pDefCustomShape->pHandles; + seqHandles.realloc( nCount ); + for ( i = 0; i < nCount; i++, pData++ ) + { + sal_Int32 nPropertiesNeeded = 1; // position is always needed + sal_Int32 nFlags = pData->nFlags; + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR ) + { + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + } + } + else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + } + + n = 0; + com::sun::star::beans::PropertyValues& rPropValues = seqHandles[ i ]; + rPropValues.realloc( nPropertiesNeeded ); + + // POSITION + { + const rtl::OUString sPosition( RTL_CONSTASCII_USTRINGPARAM ( "Position" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, pData->nPositionX, sal_True, sal_True ); + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, pData->nPositionY, sal_True, sal_False ); + rPropValues[ n ].Name = sPosition; + rPropValues[ n++ ].Value <<= aPosition; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X ) + { + const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + sal_Bool bMirroredX = sal_True; + rPropValues[ n ].Name = sMirroredX; + rPropValues[ n++ ].Value <<= bMirroredX; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y ) + { + const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + sal_Bool bMirroredY = sal_True; + rPropValues[ n ].Name = sMirroredY; + rPropValues[ n++ ].Value <<= bMirroredY; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED ) + { + const rtl::OUString sSwitched( RTL_CONSTASCII_USTRINGPARAM ( "Switched" ) ); + sal_Bool bSwitched = sal_True; + rPropValues[ n ].Name = sSwitched; + rPropValues[ n++ ].Value <<= bSwitched; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR ) + { + const rtl::OUString sPolar( RTL_CONSTASCII_USTRINGPARAM ( "Polar" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aCenter; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.First, pData->nCenterX, + ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_X_IS_SPECIAL ) != 0, sal_True ); + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.Second, pData->nCenterY, + ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_Y_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sPolar; + rPropValues[ n++ ].Value <<= aCenter; + if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRadiusRangeMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, pData->nRangeXMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRadiusRangeMinimum; + rPropValues[ n++ ].Value <<= aRadiusRangeMinimum; + } + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRadiusRangeMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, pData->nRangeXMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRadiusRangeMaximum; + rPropValues[ n++ ].Value <<= aRadiusRangeMaximum; + } + } + } + else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeXMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, pData->nRangeXMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRangeXMinimum; + rPropValues[ n++ ].Value <<= aRangeXMinimum; + } + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeXMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, pData->nRangeXMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRangeXMaximum; + rPropValues[ n++ ].Value <<= aRangeXMaximum; + } + if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeYMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, pData->nRangeYMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRangeYMinimum; + rPropValues[ n++ ].Value <<= aRangeYMinimum; + } + if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeYMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, pData->nRangeYMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRangeYMaximum; + rPropValues[ n++ ].Value <<= aRangeYMaximum; + } + } + } + aPropVal.Name = sHandles; + aPropVal.Value <<= seqHandles; + aGeometryItem.SetPropertyValue( aPropVal ); + } + SetMergedItem( aGeometryItem ); +} + +sal_Bool SdrObjCustomShape::IsDefaultGeometry( const DefaultType eDefaultType ) const +{ + sal_Bool bIsDefaultGeometry = sal_False; + + PropertyValue aPropVal; + rtl::OUString sShapeType; + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + + Any *pAny = aGeometryItem.GetPropertyValueByName( sType ); + if ( pAny ) + *pAny >>= sShapeType; + + MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType ); + + const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType ); + const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM ( "Path" ) ); + switch( eDefaultType ) + { + case DEFAULT_VIEWBOX : + { + const rtl::OUString sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) ); + const Any* pViewBox = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sViewBox ); + com::sun::star::awt::Rectangle aViewBox; + if ( pViewBox && ( *pViewBox >>= aViewBox ) ) + { + if ( ( aViewBox.Width == pDefCustomShape->nCoordWidth ) + && ( aViewBox.Height == pDefCustomShape->nCoordHeight ) ) + bIsDefaultGeometry = sal_True; + } + } + break; + + case DEFAULT_PATH : + { + const rtl::OUString sCoordinates( RTL_CONSTASCII_USTRINGPARAM ( "Coordinates" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sCoordinates ); + if ( pAny && pDefCustomShape && pDefCustomShape->nVertices && pDefCustomShape->pVertices ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates1, seqCoordinates2; + if ( *pAny >>= seqCoordinates1 ) + { + sal_Int32 i, nCount = pDefCustomShape->nVertices; + seqCoordinates2.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ i ].First, pDefCustomShape->pVertices[ i ].nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ i ].Second, pDefCustomShape->pVertices[ i ].nValB ); + } + if ( seqCoordinates1 == seqCoordinates2 ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( ( pDefCustomShape->nVertices == 0 ) || ( pDefCustomShape->pVertices == 0 ) ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_GLUEPOINTS : + { + const rtl::OUString sGluePoints( RTL_CONSTASCII_USTRINGPARAM ( "GluePoints" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sGluePoints ); + if ( pAny && pDefCustomShape && pDefCustomShape->nGluePoints && pDefCustomShape->pGluePoints ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqGluePoints1, seqGluePoints2; + if ( *pAny >>= seqGluePoints1 ) + { + sal_Int32 i, nCount = pDefCustomShape->nGluePoints; + seqGluePoints2.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints2[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqGluePoints2[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB ); + } + if ( seqGluePoints1 == seqGluePoints2 ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( pDefCustomShape->nGluePoints == 0 ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_SEGMENTS : + { + /////////////////// + // Path/Segments // + /////////////////// + const rtl::OUString sSegments( RTL_CONSTASCII_USTRINGPARAM ( "Segments" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sSegments ); + if ( pAny ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments1, seqSegments2; + if ( *pAny >>= seqSegments1 ) + { + if ( pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements ) + { + sal_Int32 i, nCount = pDefCustomShape->nElements; + if ( nCount ) + { + seqSegments2.realloc( nCount ); + for ( i = 0; i < nCount; i++ ) + { + EnhancedCustomShapeSegment& rSegInfo = seqSegments2[ i ]; + sal_uInt16 nSDat = pDefCustomShape->pElements[ i ]; + switch( nSDat >> 8 ) + { + case 0x00 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::LINETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x20 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CURVETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x40 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::MOVETO; + rSegInfo.Count = nSDat & 0xff; + if ( !rSegInfo.Count ) + rSegInfo.Count = 1; + } + break; + case 0x60 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH; + rSegInfo.Count = 0; + } + break; + case 0x80 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ENDSUBPATH; + rSegInfo.Count = 0; + } + break; + case 0xa1 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO; + rSegInfo.Count = ( nSDat & 0xff ) / 3; + } + break; + case 0xa2 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE; + rSegInfo.Count = ( nSDat & 0xff ) / 3; + } + break; + case 0xa3 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARCTO; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa4 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ARC; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa5 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa6 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC; + rSegInfo.Count = ( nSDat & 0xff ) >> 2; + } + break; + case 0xa7 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX; + rSegInfo.Count = nSDat & 0xff; + } + break; + case 0xa8 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY; + rSegInfo.Count = nSDat & 0xff; + } + break; + case 0xaa : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOFILL; + rSegInfo.Count = 0; + } + break; + case 0xab : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::NOSTROKE; + rSegInfo.Count = 0; + } + break; + default: + case 0xf8 : + { + rSegInfo.Command = EnhancedCustomShapeSegmentCommand::UNKNOWN; + rSegInfo.Count = nSDat; + } + break; + } + } + if ( seqSegments1 == seqSegments2 ) + bIsDefaultGeometry = sal_True; + } + } + else + { + // check if its the default segment description ( M L Z N ) + if ( seqSegments1.getLength() == 4 ) + { + if ( ( seqSegments1[ 0 ].Command == EnhancedCustomShapeSegmentCommand::MOVETO ) + && ( seqSegments1[ 1 ].Command == EnhancedCustomShapeSegmentCommand::LINETO ) + && ( seqSegments1[ 2 ].Command == EnhancedCustomShapeSegmentCommand::CLOSESUBPATH ) + && ( seqSegments1[ 3 ].Command == EnhancedCustomShapeSegmentCommand::ENDSUBPATH ) ) + bIsDefaultGeometry = sal_True; + } + } + } + } + else if ( pDefCustomShape && ( ( pDefCustomShape->nElements == 0 ) || ( pDefCustomShape->pElements == 0 ) ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_STRETCHX : + { + const rtl::OUString sStretchX( RTL_CONSTASCII_USTRINGPARAM ( "StretchX" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchX ); + if ( pAny && pDefCustomShape ) + { + sal_Int32 nStretchX = 0; + if ( *pAny >>= nStretchX ) + { + if ( pDefCustomShape->nXRef == nStretchX ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( pDefCustomShape->nXRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_STRETCHY : + { + const rtl::OUString sStretchY( RTL_CONSTASCII_USTRINGPARAM ( "StretchY" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sStretchY ); + if ( pAny && pDefCustomShape ) + { + sal_Int32 nStretchY = 0; + if ( *pAny >>= nStretchY ) + { + if ( pDefCustomShape->nYRef == nStretchY ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( pDefCustomShape->nYRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_EQUATIONS : + { + const rtl::OUString sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sEquations ); + if ( pAny && pDefCustomShape && pDefCustomShape->nCalculation && pDefCustomShape->pCalculation ) + { + com::sun::star::uno::Sequence< rtl::OUString > seqEquations1, seqEquations2; + if ( *pAny >>= seqEquations1 ) + { + sal_Int32 i, nCount = pDefCustomShape->nCalculation; + seqEquations2.realloc( nCount ); + + const SvxMSDffCalculationData* pData = pDefCustomShape->pCalculation; + for ( i = 0; i < nCount; i++, pData++ ) + seqEquations2[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] ); + + if ( seqEquations1 == seqEquations2 ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( ( pDefCustomShape->nCalculation == 0 ) || ( pDefCustomShape->pCalculation == 0 ) ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_TEXTFRAMES : + { + const rtl::OUString sTextFrames( RTL_CONSTASCII_USTRINGPARAM( "TextFrames" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sTextFrames ); + if ( pAny && pDefCustomShape && pDefCustomShape->nTextRect && pDefCustomShape->pTextRect ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > seqTextFrames1, seqTextFrames2; + if ( *pAny >>= seqTextFrames1 ) + { + sal_Int32 i, nCount = pDefCustomShape->nTextRect; + seqTextFrames2.realloc( nCount ); + const SvxMSDffTextRectangles* pRectangles = pDefCustomShape->pTextRect; + for ( i = 0; i < nCount; i++, pRectangles++ ) + { + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].TopLeft.First, pRectangles->nPairA.nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].TopLeft.Second, pRectangles->nPairA.nValB ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].BottomRight.First, pRectangles->nPairB.nValA ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqTextFrames2[ i ].BottomRight.Second, pRectangles->nPairB.nValB ); + } + if ( seqTextFrames1 == seqTextFrames2 ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( ( pDefCustomShape->nTextRect == 0 ) || ( pDefCustomShape->pTextRect == 0 ) ) ) + bIsDefaultGeometry = sal_True; + } + break; + + case DEFAULT_HANDLES : + { + const rtl::OUString sHandles( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) ); + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sHandles ); + if ( pAny && pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles ) + { + com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValues > seqHandles1, seqHandles2; + if ( *pAny >>= seqHandles1 ) + { + sal_Int32 i, n, nCount = pDefCustomShape->nHandles; + const SvxMSDffHandle* pData = pDefCustomShape->pHandles; + seqHandles2.realloc( nCount ); + for ( i = 0; i < nCount; i++, pData++ ) + { + sal_Int32 nPropertiesNeeded = 1; // position is always needed + sal_Int32 nFlags = pData->nFlags; + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED ) + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR ) + { + nPropertiesNeeded++; + if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + } + } + else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + nPropertiesNeeded++; + } + + n = 0; + com::sun::star::beans::PropertyValues& rPropValues = seqHandles2[ i ]; + rPropValues.realloc( nPropertiesNeeded ); + + // POSITION + { + const rtl::OUString sPosition( RTL_CONSTASCII_USTRINGPARAM ( "Position" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, pData->nPositionX, sal_True, sal_True ); + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, pData->nPositionY, sal_True, sal_False ); + rPropValues[ n ].Name = sPosition; + rPropValues[ n++ ].Value <<= aPosition; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X ) + { + const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + sal_Bool bMirroredX = sal_True; + rPropValues[ n ].Name = sMirroredX; + rPropValues[ n++ ].Value <<= bMirroredX; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y ) + { + const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + sal_Bool bMirroredY = sal_True; + rPropValues[ n ].Name = sMirroredY; + rPropValues[ n++ ].Value <<= bMirroredY; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED ) + { + const rtl::OUString sSwitched( RTL_CONSTASCII_USTRINGPARAM ( "Switched" ) ); + sal_Bool bSwitched = sal_True; + rPropValues[ n ].Name = sSwitched; + rPropValues[ n++ ].Value <<= bSwitched; + } + if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR ) + { + const rtl::OUString sPolar( RTL_CONSTASCII_USTRINGPARAM ( "Polar" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameterPair aCenter; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.First, pData->nCenterX, + ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_X_IS_SPECIAL ) != 0, sal_True ); + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.Second, pData->nCenterY, + ( nFlags & MSDFF_HANDLE_FLAGS_CENTER_Y_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sPolar; + rPropValues[ n++ ].Value <<= aCenter; + if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRadiusRangeMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, pData->nRangeXMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRadiusRangeMinimum; + rPropValues[ n++ ].Value <<= aRadiusRangeMinimum; + } + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRadiusRangeMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, pData->nRangeXMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRadiusRangeMaximum; + rPropValues[ n++ ].Value <<= aRadiusRangeMaximum; + } + } + } + else if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE ) + { + if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeXMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, pData->nRangeXMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRangeXMinimum; + rPropValues[ n++ ].Value <<= aRangeXMinimum; + } + if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeXMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeXMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, pData->nRangeXMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRangeXMaximum; + rPropValues[ n++ ].Value <<= aRangeXMaximum; + } + if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeYMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMinimum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, pData->nRangeYMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MIN_IS_SPECIAL ) != 0, sal_True ); + rPropValues[ n ].Name = sRangeYMinimum; + rPropValues[ n++ ].Value <<= aRangeYMinimum; + } + if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) + { + const rtl::OUString sRangeYMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMaximum" ) ); + ::com::sun::star::drawing::EnhancedCustomShapeParameter aRangeYMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, pData->nRangeYMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MAX_IS_SPECIAL ) != 0, sal_False ); + rPropValues[ n ].Name = sRangeYMaximum; + rPropValues[ n++ ].Value <<= aRangeYMaximum; + } + } + } + if ( seqHandles1 == seqHandles2 ) + bIsDefaultGeometry = sal_True; + } + } + else if ( pDefCustomShape && ( ( pDefCustomShape->nHandles == 0 ) || ( pDefCustomShape->pHandles == 0 ) ) ) + bIsDefaultGeometry = sal_True; + } + break; + } + return bIsDefaultGeometry; +} + +void SdrObjCustomShape::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bResizeFreeAllowed=fObjectRotation == 0.0; + rInfo.bResizePropAllowed=TRUE; + rInfo.bRotateFreeAllowed=TRUE; + rInfo.bRotate90Allowed =TRUE; + rInfo.bMirrorFreeAllowed=TRUE; + rInfo.bMirror45Allowed =TRUE; + rInfo.bMirror90Allowed =TRUE; + rInfo.bTransparenceAllowed = FALSE; + rInfo.bGradientAllowed = FALSE; + rInfo.bShearAllowed =TRUE; + rInfo.bEdgeRadiusAllowed=FALSE; + rInfo.bNoContortion =TRUE; + + // #i37011# + if ( mXRenderedCustomShape.is() ) + { + const SdrObject* pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape ); + if ( pRenderedCustomShape ) + { + // #i37262# + // Iterate self over the contained objects, since there are combinations of + // polygon and curve objects. In that case, aInfo.bCanConvToPath and + // aInfo.bCanConvToPoly would be false. What is needed here is an or, not an and. + SdrObjListIter aIterator(*pRenderedCustomShape); + while(aIterator.IsMore()) + { + SdrObject* pCandidate = aIterator.Next(); + SdrObjTransformInfoRec aInfo; + pCandidate->TakeObjInfo(aInfo); + + // set path and poly conversion if one is possible since + // this object will first be broken + const sal_Bool bCanConvToPathOrPoly(aInfo.bCanConvToPath || aInfo.bCanConvToPoly); + if(rInfo.bCanConvToPath != bCanConvToPathOrPoly) + { + rInfo.bCanConvToPath = bCanConvToPathOrPoly; + } + + if(rInfo.bCanConvToPoly != bCanConvToPathOrPoly) + { + rInfo.bCanConvToPoly = bCanConvToPathOrPoly; + } + + if(rInfo.bCanConvToContour != aInfo.bCanConvToContour) + { + rInfo.bCanConvToContour = aInfo.bCanConvToContour; + } + } + } + } +} + +void SdrObjCustomShape::SetModel(SdrModel* pNewModel) +{ + SdrTextObj::SetModel(pNewModel); + mXRenderedCustomShape.clear(); +} + +UINT16 SdrObjCustomShape::GetObjIdentifier() const +{ + return UINT16(OBJ_CUSTOMSHAPE); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrObjCustomShape::RecalcSnapRect() +{ + SdrTextObj::RecalcSnapRect(); +} +const Rectangle& SdrObjCustomShape::GetSnapRect() const +{ + return SdrTextObj::GetSnapRect(); +} +const Rectangle& SdrObjCustomShape::GetCurrentBoundRect() const +{ + return SdrTextObj::GetCurrentBoundRect(); +} +const Rectangle& SdrObjCustomShape::GetLogicRect() const +{ + return SdrTextObj::GetLogicRect(); +} +void SdrObjCustomShape::NbcSetSnapRect( const Rectangle& rRect ) +{ + aRect=rRect; + ImpJustifyRect(aRect); + InvalidateRenderGeometry(); + Rectangle aTextBound( aRect ); + if ( GetTextBounds( aTextBound ) ) + { + if ( pModel==NULL || !pModel->IsPasteResize() ) + { + long nHDist=GetTextLeftDistance()+GetTextRightDistance(); + long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); + long nTWdt=aTextBound.GetWidth ()-1-nHDist; if (nTWdt<0) nTWdt=0; + long nTHgt=aTextBound.GetHeight()-1-nVDist; if (nTHgt<0) nTHgt=0; + if ( IsAutoGrowWidth() ) + NbcSetMinTextFrameWidth( nTWdt ); + if ( IsAutoGrowHeight() ) + NbcSetMinTextFrameHeight( nTHgt ); + NbcAdjustTextFrameWidthAndHeight(); + } + } + ImpCheckShear(); + SetRectsDirty(); + SetChanged(); +} +void SdrObjCustomShape::SetSnapRect( const Rectangle& rRect ) +{ + Rectangle aBoundRect0; + if ( pUserCall ) + aBoundRect0 = GetLastBoundRect(); + NbcSetSnapRect( rRect ); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} +void SdrObjCustomShape::NbcSetLogicRect( const Rectangle& rRect ) +{ + aRect = rRect; + ImpJustifyRect( aRect ); + InvalidateRenderGeometry(); + Rectangle aTextBound( aRect ); + if ( GetTextBounds( aTextBound ) ) + { + long nHDist=GetTextLeftDistance()+GetTextRightDistance(); + long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); + + long nTWdt=aTextBound.GetWidth()-1-nHDist; if (nTWdt<0) nTWdt=0; + long nTHgt=aTextBound.GetHeight()-1-nVDist; if (nTHgt<0) nTHgt=0; + if ( IsAutoGrowWidth() ) + NbcSetMinTextFrameWidth( nTWdt ); + if ( IsAutoGrowHeight() ) + NbcSetMinTextFrameHeight( nTHgt ); + NbcAdjustTextFrameWidthAndHeight(); + } + SetRectsDirty(); + SetChanged(); +} +void SdrObjCustomShape::SetLogicRect( const Rectangle& rRect ) +{ + Rectangle aBoundRect0; + if ( pUserCall ) + aBoundRect0 = GetLastBoundRect(); + NbcSetLogicRect(rRect); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); +} +void SdrObjCustomShape::Move( const Size& rSiz ) +{ + if ( rSiz.Width() || rSiz.Height() ) + { + Rectangle aBoundRect0; + if ( pUserCall ) + aBoundRect0 = GetLastBoundRect(); + // #110094#-14 SendRepaintBroadcast(); + NbcMove(rSiz); + SetChanged(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0); + } +} +void SdrObjCustomShape::NbcMove( const Size& rSiz ) +{ + SdrTextObj::NbcMove( rSiz ); + if ( mXRenderedCustomShape.is() ) + { + SdrObject* pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape ); + if ( pRenderedCustomShape ) + { + // #i97149# the visualisation shape needs to be informed + // about change, too + pRenderedCustomShape->ActionChanged(); + pRenderedCustomShape->NbcMove( rSiz ); + } + } + + // #i37011# adapt geometry shadow + if(mpLastShadowGeometry) + { + mpLastShadowGeometry->NbcMove( rSiz ); + } +} +void SdrObjCustomShape::Resize( const Point& rRef, const Fraction& xFact, const Fraction& yFact ) +{ + SdrTextObj::Resize( rRef, xFact, yFact ); +} + +void SdrObjCustomShape::NbcResize( const Point& rRef, const Fraction& rxFact, const Fraction& ryFact ) +{ + Fraction xFact( rxFact ); + Fraction yFact( ryFact ); + + // taking care of handles that should not been changed + Rectangle aOld( aRect ); + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + + SdrTextObj::NbcResize( rRef, xFact, yFact ); + + if ( ( xFact.GetNumerator() != xFact.GetDenominator() ) + || ( yFact.GetNumerator()!= yFact.GetDenominator() ) ) + { + if ( ( ( xFact.GetNumerator() < 0 ) && ( xFact.GetDenominator() > 0 ) ) || + ( ( xFact.GetNumerator() > 0 ) && ( xFact.GetDenominator() < 0 ) ) ) + { + SetMirroredX( IsMirroredX() == sal_False ); + } + if ( ( ( yFact.GetNumerator() < 0 ) && ( yFact.GetDenominator() > 0 ) ) || + ( ( yFact.GetNumerator() > 0 ) && ( yFact.GetDenominator() < 0 ) ) ) + { + SetMirroredY( IsMirroredY() == sal_False ); + } + } + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + try + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED ) + aIter->xInteraction->setControllerPosition( aIter->aPosition ); + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X ) + { + sal_Int32 nX = ( aIter->aPosition.X - aOld.Left() ) + aRect.Left(); + aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( nX, aIter->xInteraction->getPosition().Y ) ); + } + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y ) + { + sal_Int32 nY = ( aIter->aPosition.Y - aOld.Top() ) + aRect.Top(); + aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( aIter->xInteraction->getPosition().X, nY ) ); + } + } + catch ( const uno::RuntimeException& ) + { + } + aIter++; + } + InvalidateRenderGeometry(); +} +void SdrObjCustomShape::NbcRotate( const Point& rRef, long nWink, double sn, double cs ) +{ + sal_Bool bMirroredX = IsMirroredX(); + sal_Bool bMirroredY = IsMirroredY(); + + fObjectRotation = fmod( fObjectRotation, 360.0 ); + if ( fObjectRotation < 0 ) + fObjectRotation = 360 + fObjectRotation; + + // the rotation angle for ashapes is stored in fObjectRotation, this rotation + // has to be applied to the text object (which is internally using aGeo.nWink). + SdrTextObj::NbcRotate( aRect.TopLeft(), -aGeo.nDrehWink, // retrieving the unrotated text object + sin( (-aGeo.nDrehWink) * F_PI18000 ), + cos( (-aGeo.nDrehWink) * F_PI18000 ) ); + aGeo.nDrehWink = 0; // resetting aGeo data + aGeo.RecalcSinCos(); + + long nW = (long)( fObjectRotation * 100 ); // applying our object rotation + if ( bMirroredX ) + nW = 36000 - nW; + if ( bMirroredY ) + nW = 18000 - nW; + nW = nW % 36000; + if ( nW < 0 ) + nW = 36000 + nW; + SdrTextObj::NbcRotate( aRect.TopLeft(), nW, // applying text rotation + sin( nW * F_PI18000 ), + cos( nW * F_PI18000 ) ); + + int nSwap = 0; + if ( bMirroredX ) + nSwap ^= 1; + if ( bMirroredY ) + nSwap ^= 1; + + double fWink = nWink; // updating to our new object rotation + fWink /= 100.0; + fObjectRotation = fmod( nSwap ? fObjectRotation - fWink : fObjectRotation + fWink, 360.0 ); + if ( fObjectRotation < 0 ) + fObjectRotation = 360 + fObjectRotation; + + SdrTextObj::NbcRotate( rRef, nWink, sn, cs ); // applying text rotation + InvalidateRenderGeometry(); +} + +void SdrObjCustomShape::NbcMirror( const Point& rRef1, const Point& rRef2 ) +{ + // storing horizontal and vertical flipping without modifying the rotate angle + + sal_Bool bHorz = sal_False; + sal_Bool bVert = sal_False; + if ( rRef1.X() == rRef2.X() ) + bHorz = sal_True; + if ( rRef1.Y() == rRef2.Y() ) + bVert = sal_True; + if ( !bHorz && !bVert ) + bHorz = bVert = sal_True; + + if ( bHorz || bVert ) + { + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + + ///////////////// + // "MirroredX" // + ///////////////// + if ( bHorz ) + { + const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredX ); + if ( pAny ) + { + sal_Bool bFlip = sal_Bool(); + if ( *pAny >>= bFlip ) + { + if ( bFlip ) + bHorz = sal_False; + } + } + PropertyValue aPropVal; + aPropVal.Name = sMirroredX; + aPropVal.Value <<= bHorz; + aGeometryItem.SetPropertyValue( aPropVal ); + } + + ///////////////// + // "MirroredY" // + ///////////////// + if ( bVert ) + { + const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sMirroredY ); + if ( pAny ) + { + sal_Bool bFlip = sal_Bool(); + if ( *pAny >>= bFlip ) + { + if ( bFlip ) + bVert = sal_False; + } + } + PropertyValue aPropVal; + aPropVal.Name = sMirroredY; + aPropVal.Value <<= bVert; + aGeometryItem.SetPropertyValue( aPropVal ); + } + SetMergedItem( aGeometryItem ); + } + SdrTextObj::NbcMirror( rRef1, rRef2 ); + InvalidateRenderGeometry(); +} + +void SdrObjCustomShape::Shear( const Point& rRef, long nWink, double tn, FASTBOOL bVShear ) +{ + SdrTextObj::Shear( rRef, nWink, tn, bVShear ); + InvalidateRenderGeometry(); +} +void SdrObjCustomShape::NbcShear( const Point& rRef, long nWink, double tn, FASTBOOL bVShear ) +{ + long nDrehWink = aGeo.nDrehWink; + if ( nDrehWink ) + { + aGeo.nDrehWink = -nDrehWink; + aGeo.RecalcSinCos(); + NbcRotate( rRef, aGeo.nDrehWink, aGeo.nSin, aGeo.nCos ); + } + SdrTextObj::NbcShear(rRef,nWink,tn,bVShear); + if ( nDrehWink ) + { + aGeo.nDrehWink = nDrehWink; + aGeo.RecalcSinCos(); + Rotate( rRef, aGeo.nDrehWink, aGeo.nSin, aGeo.nCos ); + } + InvalidateRenderGeometry(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrGluePoint SdrObjCustomShape::GetVertexGluePoint(USHORT nPosNum) const +{ + INT32 nWdt = ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue(); + + // #i25616# + if(!LineIsOutsideGeometry()) + { + nWdt++; + nWdt /= 2; + } + + Point aPt; + switch (nPosNum) { + case 0: aPt=aRect.TopCenter(); aPt.Y()-=nWdt; break; + case 1: aPt=aRect.RightCenter(); aPt.X()+=nWdt; break; + case 2: aPt=aRect.BottomCenter(); aPt.Y()+=nWdt; break; + case 3: aPt=aRect.LeftCenter(); aPt.X()-=nWdt; break; + } + if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan); + if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); + aPt-=GetSnapRect().Center(); + SdrGluePoint aGP(aPt); + aGP.SetPercent(FALSE); + return aGP; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// #i38892# +void SdrObjCustomShape::ImpCheckCustomGluePointsAreAdded() +{ + const SdrObject* pSdrObject = GetSdrObjectFromCustomShape(); + + if(pSdrObject) + { + const SdrGluePointList* pSource = pSdrObject->GetGluePointList(); + + if(pSource && pSource->GetCount()) + { + if(!SdrTextObj::GetGluePointList()) + { + SdrTextObj::ForceGluePointList(); + } + + const SdrGluePointList* pList = SdrTextObj::GetGluePointList(); + + if(pList) + { + SdrGluePointList aNewList; + sal_uInt16 a; + + for(a = 0; a < pSource->GetCount(); a++) + { + SdrGluePoint aCopy((*pSource)[a]); + aCopy.SetUserDefined(FALSE); + aNewList.Insert(aCopy); + } + + sal_Bool bMirroredX = IsMirroredX(); + sal_Bool bMirroredY = IsMirroredY(); + + long nShearWink = aGeo.nShearWink; + double fTan = aGeo.nTan; + + if ( aGeo.nDrehWink || nShearWink || bMirroredX || bMirroredY ) + { + Polygon aPoly( aRect ); + if( nShearWink ) + { + USHORT nPointCount=aPoly.GetSize(); + for (USHORT i=0; i<nPointCount; i++) + ShearPoint(aPoly[i],aRect.Center(), fTan, FALSE ); + } + if ( aGeo.nDrehWink ) + aPoly.Rotate( aRect.Center(), aGeo.nDrehWink / 10 ); + + Rectangle aBoundRect( aPoly.GetBoundRect() ); + sal_Int32 nXDiff = aBoundRect.Left() - aRect.Left(); + sal_Int32 nYDiff = aBoundRect.Top() - aRect.Top(); + + if (nShearWink&&((bMirroredX&&!bMirroredY)||(bMirroredY&&!bMirroredX))) + { + nShearWink = -nShearWink; + fTan = -fTan; + } + + Point aRef( aRect.GetWidth() / 2, aRect.GetHeight() / 2 ); + for ( a = 0; a < aNewList.GetCount(); a++ ) + { + SdrGluePoint& rPoint = aNewList[ a ]; + Point aGlue( rPoint.GetPos() ); + if ( nShearWink ) + ShearPoint( aGlue, aRef, fTan ); + + RotatePoint( aGlue, aRef, sin( fObjectRotation * F_PI180 ), cos( fObjectRotation * F_PI180 ) ); + if ( bMirroredX ) + aGlue.X() = aRect.GetWidth() - aGlue.X(); + if ( bMirroredY ) + aGlue.Y() = aRect.GetHeight() - aGlue.Y(); + aGlue.X() -= nXDiff; + aGlue.Y() -= nYDiff; + rPoint.SetPos( aGlue ); + } + } + + for(a = 0; a < pList->GetCount(); a++) + { + const SdrGluePoint& rCandidate = (*pList)[a]; + + if(rCandidate.IsUserDefined()) + { + aNewList.Insert(rCandidate); + } + } + + // copy new list to local. This is NOT very convenient behaviour, the local + // GluePointList should not be set, but be delivered by using GetGluePointList(), + // maybe on demand. Since the local object is changed here, this is assumed to + // be a result of GetGluePointList and thus the list is copied + if(pPlusData) + { + *pPlusData->pGluePoints = aNewList; + } + } + } + } +} + +// #i38892# +const SdrGluePointList* SdrObjCustomShape::GetGluePointList() const +{ + ((SdrObjCustomShape*)this)->ImpCheckCustomGluePointsAreAdded(); + return SdrTextObj::GetGluePointList(); +} + +// #i38892# +//SdrGluePointList* SdrObjCustomShape::GetGluePointList() +//{ +// ImpCheckCustomGluePointsAreAdded(); +// return SdrTextObj::GetGluePointList(); +//} + +// #i38892# +SdrGluePointList* SdrObjCustomShape::ForceGluePointList() +{ + if(SdrTextObj::ForceGluePointList()) + { + ImpCheckCustomGluePointsAreAdded(); + return SdrTextObj::ForceGluePointList(); + } + else + { + return 0L; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +sal_uInt32 SdrObjCustomShape::GetHdlCount() const +{ + const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount()); + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + return ( aInteractionHandles.size() + nBasicHdlCount ); +} + +SdrHdl* SdrObjCustomShape::GetHdl( sal_uInt32 nHdlNum ) const +{ + SdrHdl* pH = NULL; + const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount()); + + if ( nHdlNum < nBasicHdlCount ) + pH = SdrTextObj::GetHdl( nHdlNum ); + else + { + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + const sal_uInt32 nCustomShapeHdlNum(nHdlNum - nBasicHdlCount); + + if ( nCustomShapeHdlNum < aInteractionHandles.size() ) + { + if ( aInteractionHandles[ nCustomShapeHdlNum ].xInteraction.is() ) + { + try + { + com::sun::star::awt::Point aPosition( aInteractionHandles[ nCustomShapeHdlNum ].xInteraction->getPosition() ); + pH = new SdrHdl( Point( aPosition.X, aPosition.Y ), HDL_CUSTOMSHAPE1 ); + pH->SetPointNum( nCustomShapeHdlNum ); + pH->SetObj( (SdrObject*)this ); + } + catch ( const uno::RuntimeException& ) + { + } + } + } + } + return pH; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SdrObjCustomShape::hasSpecialDrag() const +{ + return true; +} + +bool SdrObjCustomShape::beginSpecialDrag(SdrDragStat& rDrag) const +{ + const SdrHdl* pHdl = rDrag.GetHdl(); + + if(pHdl && HDL_CUSTOMSHAPE1 == pHdl->GetKind()) + { + rDrag.SetEndDragChangesAttributes(true); + rDrag.SetNoSnap(true); + } + else + { + const SdrHdl* pHdl2 = rDrag.GetHdl(); + const SdrHdlKind eHdl((pHdl2 == NULL) ? HDL_MOVE : pHdl2->GetKind()); + + switch( eHdl ) + { + case HDL_UPLFT : + case HDL_UPPER : + case HDL_UPRGT : + case HDL_LEFT : + case HDL_RIGHT : + case HDL_LWLFT : + case HDL_LOWER : + case HDL_LWRGT : + case HDL_MOVE : + { + break; + } + default: + { + return false; + } + } + } + + return true; +} + +void SdrObjCustomShape::DragResizeCustomShape( const Rectangle& rNewRect, SdrObjCustomShape* pObj ) const +{ + Rectangle aOld( pObj->aRect ); + sal_Bool bOldMirroredX( pObj->IsMirroredX() ); + sal_Bool bOldMirroredY( pObj->IsMirroredY() ); + + Rectangle aNewRect( rNewRect ); + aNewRect.Justify(); + + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( pObj ) ); + + GeoStat aGeoStat( pObj->GetGeoStat() ); + if ( aNewRect.TopLeft()!= pObj->aRect.TopLeft() && + ( pObj->aGeo.nDrehWink || pObj->aGeo.nShearWink ) ) + { + Point aNewPos( aNewRect.TopLeft() ); + if ( pObj->aGeo.nShearWink ) ShearPoint( aNewPos, aOld.TopLeft(), aGeoStat.nTan ); + if ( pObj->aGeo.nDrehWink ) RotatePoint(aNewPos, aOld.TopLeft(), aGeoStat.nSin, aGeoStat.nCos ); + aNewRect.SetPos( aNewPos ); + } + if ( aNewRect != pObj->aRect ) + { + pObj->SetLogicRect( aNewRect ); + pObj->InvalidateRenderGeometry(); + + if ( rNewRect.Left() > rNewRect.Right() ) + { + Point aTop( ( pObj->GetSnapRect().Left() + pObj->GetSnapRect().Right() ) >> 1, pObj->GetSnapRect().Top() ); + Point aBottom( aTop.X(), aTop.Y() + 1000 ); + pObj->NbcMirror( aTop, aBottom ); + } + if ( rNewRect.Top() > rNewRect.Bottom() ) + { + Point aLeft( pObj->GetSnapRect().Left(), ( pObj->GetSnapRect().Top() + pObj->GetSnapRect().Bottom() ) >> 1 ); + Point aRight( aLeft.X() + 1000, aLeft.Y() ); + pObj->NbcMirror( aLeft, aRight ); + } + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + try + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED ) + aIter->xInteraction->setControllerPosition( aIter->aPosition ); + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_X ) + { + sal_Int32 nX; + if ( bOldMirroredX ) + { + nX = ( aIter->aPosition.X - aOld.Right() ); + if ( rNewRect.Left() > rNewRect.Right() ) + nX = pObj->aRect.Left() - nX; + else + nX += pObj->aRect.Right(); + } + else + { + nX = ( aIter->aPosition.X - aOld.Left() ); + if ( rNewRect.Left() > rNewRect.Right() ) + nX = pObj->aRect.Right() - nX; + else + nX += pObj->aRect.Left(); + } + aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( nX, aIter->xInteraction->getPosition().Y ) ); + } + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_ABSOLUTE_Y ) + { + sal_Int32 nY; + if ( bOldMirroredY ) + { + nY = ( aIter->aPosition.Y - aOld.Bottom() ); + if ( rNewRect.Top() > rNewRect.Bottom() ) + nY = pObj->aRect.Top() - nY; + else + nY += pObj->aRect.Bottom(); + } + else + { + nY = ( aIter->aPosition.Y - aOld.Top() ); + if ( rNewRect.Top() > rNewRect.Bottom() ) + nY = pObj->aRect.Bottom() - nY; + else + nY += pObj->aRect.Top(); + } + aIter->xInteraction->setControllerPosition( com::sun::star::awt::Point( aIter->xInteraction->getPosition().X, nY ) ); + } + } + catch ( const uno::RuntimeException& ) + { + } + aIter++; + } + } +} + +void SdrObjCustomShape::DragMoveCustomShapeHdl( const Point aDestination, const sal_uInt16 nCustomShapeHdlNum, SdrObjCustomShape* pObj ) const +{ + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( pObj ) ); + if ( nCustomShapeHdlNum < aInteractionHandles.size() ) + { + SdrCustomShapeInteraction aInteractionHandle( aInteractionHandles[ nCustomShapeHdlNum ] ); + if ( aInteractionHandle.xInteraction.is() ) + { + try + { + com::sun::star::awt::Point aPt( aDestination.X(), aDestination.Y() ); + if ( aInteractionHandle.nMode & CUSTOMSHAPE_HANDLE_MOVE_SHAPE ) + { + sal_Int32 nXDiff = aPt.X - aInteractionHandle.aPosition.X; + sal_Int32 nYDiff = aPt.Y - aInteractionHandle.aPosition.Y; + + pObj->aRect.Move( nXDiff, nYDiff ); + pObj->aOutRect.Move( nXDiff, nYDiff ); + pObj->maSnapRect.Move( nXDiff, nYDiff ); + pObj->SetRectsDirty(sal_True); + pObj->InvalidateRenderGeometry(); + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED ) + { + if ( aIter->xInteraction.is() ) + aIter->xInteraction->setControllerPosition( aIter->aPosition ); + } + aIter++; + } + } + aInteractionHandle.xInteraction->setControllerPosition( aPt ); + } + catch ( const uno::RuntimeException& ) + { + } + } + } +} + +bool SdrObjCustomShape::applySpecialDrag(SdrDragStat& rDrag) +{ + const SdrHdl* pHdl = rDrag.GetHdl(); + const SdrHdlKind eHdl((pHdl == NULL) ? HDL_MOVE : pHdl->GetKind()); + + switch(eHdl) + { + case HDL_CUSTOMSHAPE1 : + { + rDrag.SetEndDragChangesGeoAndAttributes(true); + DragMoveCustomShapeHdl( rDrag.GetNow(), (sal_uInt16)pHdl->GetPointNum(), this ); + SetRectsDirty(); + InvalidateRenderGeometry(); + SetChanged(); + break; + } + + case HDL_UPLFT : + case HDL_UPPER : + case HDL_UPRGT : + case HDL_LEFT : + case HDL_RIGHT : + case HDL_LWLFT : + case HDL_LOWER : + case HDL_LWRGT : + { + DragResizeCustomShape(ImpDragCalcRect(rDrag), this); + break; + } + case HDL_MOVE : + { + Move(Size(rDrag.GetDX(), rDrag.GetDY())); + break; + } + default: break; + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrObjCustomShape::DragCreateObject( SdrDragStat& rStat ) +{ + Rectangle aRect1; + rStat.TakeCreateRect( aRect1 ); + + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + + sal_uInt32 nDefaultObjectSizeWidth = 3000; // default width from SDOptions ? + sal_uInt32 nDefaultObjectSizeHeight= 3000; + + if ( ImpVerticalSwitch( *this ) ) + { + SetMirroredX( aRect1.Left() > aRect1.Right() ); + + aRect1 = Rectangle( rStat.GetNow(), Size( nDefaultObjectSizeWidth, nDefaultObjectSizeHeight ) ); + // subtracting the horizontal difference of the latest handle from shape position + if ( aInteractionHandles.size() ) + { + sal_Int32 nHandlePos = aInteractionHandles[ aInteractionHandles.size() - 1 ].xInteraction->getPosition().X; + aRect1.Move( aRect.Left() - nHandlePos, 0 ); + } + } + ImpJustifyRect( aRect1 ); + rStat.SetActionRect( aRect1 ); + aRect = aRect1; + SetRectsDirty(); + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + try + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_CREATE_FIXED ) + aIter->xInteraction->setControllerPosition( awt::Point( rStat.GetStart().X(), rStat.GetStart().Y() ) ); + } + catch ( const uno::RuntimeException& ) + { + } + aIter++; + } + + SetBoundRectDirty(); + bSnapRectDirty=TRUE; +} + +FASTBOOL SdrObjCustomShape::BegCreate( SdrDragStat& rDrag ) +{ + return SdrTextObj::BegCreate( rDrag ); +} + +FASTBOOL SdrObjCustomShape::MovCreate(SdrDragStat& rStat) +{ + SdrView* pView = rStat.GetView(); // #i37448# + if( pView && pView->IsSolidDragging() ) + { + InvalidateRenderGeometry(); + } + DragCreateObject( rStat ); + SetRectsDirty(); + return TRUE; +} + +FASTBOOL SdrObjCustomShape::EndCreate( SdrDragStat& rStat, SdrCreateCmd eCmd ) +{ + DragCreateObject( rStat ); + + if ( bTextFrame ) + { + if ( IsAutoGrowHeight() ) + { + // MinTextHeight + long nHgt=aRect.GetHeight()-1; + if (nHgt==1) nHgt=0; + NbcSetMinTextFrameHeight( nHgt ); + } + if ( IsAutoGrowWidth() ) + { + // MinTextWidth + long nWdt=aRect.GetWidth()-1; + if (nWdt==1) nWdt=0; + NbcSetMinTextFrameWidth( nWdt ); + } + // Textrahmen neu berechnen + NbcAdjustTextFrameWidthAndHeight(); + } + SetRectsDirty(); + return ( eCmd == SDRCREATE_FORCEEND || rStat.GetPointAnz() >= 2 ); +} + +basegfx::B2DPolyPolygon SdrObjCustomShape::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const +{ + return GetLineGeometry( this, sal_False ); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// in context with the SdrObjCustomShape the SdrTextAutoGrowHeightItem == true -> Resize Shape to fit text, +// the SdrTextAutoGrowWidthItem == true -> Word wrap text in Shape +FASTBOOL SdrObjCustomShape::IsAutoGrowHeight() const +{ + const SfxItemSet& rSet = GetMergedItemSet(); + FASTBOOL bIsAutoGrowHeight = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue(); + if ( bIsAutoGrowHeight && IsVerticalWriting() ) + bIsAutoGrowHeight = ((SdrTextWordWrapItem&)(rSet.Get(SDRATTR_TEXT_WORDWRAP))).GetValue() == FALSE; + return bIsAutoGrowHeight; +} +FASTBOOL SdrObjCustomShape::IsAutoGrowWidth() const +{ + const SfxItemSet& rSet = GetMergedItemSet(); + FASTBOOL bIsAutoGrowWidth = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue(); + if ( bIsAutoGrowWidth && !IsVerticalWriting() ) + bIsAutoGrowWidth = ((SdrTextWordWrapItem&)(rSet.Get(SDRATTR_TEXT_WORDWRAP))).GetValue() == FALSE; + return bIsAutoGrowWidth; +} + +/* The following method is identical to the SdrTextObj::SetVerticalWriting method, the only difference + is that the SdrAutoGrowWidthItem and SdrAutoGrowHeightItem are not exchanged if the vertical writing + mode has been changed */ + +void SdrObjCustomShape::SetVerticalWriting( sal_Bool bVertical ) +{ + ForceOutlinerParaObject(); + + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + + DBG_ASSERT( pOutlinerParaObject, "SdrTextObj::SetVerticalWriting() without OutlinerParaObject!" ); + + if( pOutlinerParaObject ) + { + if(pOutlinerParaObject->IsVertical() != (bool)bVertical) + { + // get item settings + const SfxItemSet& rSet = GetObjectItemSet(); + + // #103516# Also exchange hor/ver adjust items + SdrTextHorzAdjust eHorz = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue(); + SdrTextVertAdjust eVert = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue(); + + // rescue object size + Rectangle aObjectRect = GetSnapRect(); + + // prepare ItemSet to set exchanged width and height items + SfxItemSet aNewSet(*rSet.GetPool(), + SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT, + // #103516# Expanded item ranges to also support hor and ver adjust. + SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST, + SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST, + 0, 0); + + aNewSet.Put(rSet); + + // #103516# Exchange horz and vert adjusts + switch(eVert) + { + case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break; + case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break; + case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break; + case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break; + } + switch(eHorz) + { + case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break; + case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break; + case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break; + case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break; + } + + SetObjectItemSet( aNewSet ); + pOutlinerParaObject = GetOutlinerParaObject(); + if ( pOutlinerParaObject ) + pOutlinerParaObject->SetVertical(bVertical); + + // restore object size + SetSnapRect(aObjectRect); + } + } +} +FASTBOOL SdrObjCustomShape::AdjustTextFrameWidthAndHeight(Rectangle& rR, FASTBOOL bHgt, FASTBOOL bWdt) const +{ + if ( pModel && HasText() && !rR.IsEmpty() ) + { + FASTBOOL bWdtGrow=bWdt && IsAutoGrowWidth(); + FASTBOOL bHgtGrow=bHgt && IsAutoGrowHeight(); + if ( bWdtGrow || bHgtGrow ) + { + Rectangle aR0(rR); + long nHgt=0,nMinHgt=0,nMaxHgt=0; + long nWdt=0,nMinWdt=0,nMaxWdt=0; + Size aSiz(rR.GetSize()); aSiz.Width()--; aSiz.Height()--; + Size aMaxSiz(100000,100000); + Size aTmpSiz(pModel->GetMaxObjSize()); + if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width(); + if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height(); + if (bWdtGrow) + { + nMinWdt=GetMinTextFrameWidth(); + nMaxWdt=GetMaxTextFrameWidth(); + if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width(); + if (nMinWdt<=0) nMinWdt=1; + aSiz.Width()=nMaxWdt; + } + if (bHgtGrow) + { + nMinHgt=GetMinTextFrameHeight(); + nMaxHgt=GetMaxTextFrameHeight(); + if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height(); + if (nMinHgt<=0) nMinHgt=1; + aSiz.Height()=nMaxHgt; + } + long nHDist=GetTextLeftDistance()+GetTextRightDistance(); + long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); + aSiz.Width()-=nHDist; + aSiz.Height()-=nVDist; + if ( aSiz.Width() < 2 ) + aSiz.Width() = 2; // Mindestgroesse 2 + if ( aSiz.Height() < 2 ) + aSiz.Height() = 2; // Mindestgroesse 2 + + if(pEdtOutl) + { + pEdtOutl->SetMaxAutoPaperSize( aSiz ); + if (bWdtGrow) + { + Size aSiz2(pEdtOutl->CalcTextSize()); + nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz + if (bHgtGrow) nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz + } else + { + nHgt=pEdtOutl->GetTextHeight()+1; // lieber etwas Tolleranz + } + } + else + { + Outliner& rOutliner=ImpGetDrawOutliner(); + rOutliner.SetPaperSize(aSiz); + rOutliner.SetUpdateMode(TRUE); + // !!! hier sollte ich wohl auch noch mal die Optimierung mit + // bPortionInfoChecked usw einbauen + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); + if( pOutlinerParaObject != NULL ) + { + rOutliner.SetText(*pOutlinerParaObject); + rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue()); + } + if ( bWdtGrow ) + { + Size aSiz2(rOutliner.CalcTextSize()); + nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz + if ( bHgtGrow ) + nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz + } + else + nHgt = rOutliner.GetTextHeight()+1; // lieber etwas Tolleranz + rOutliner.Clear(); + } + if ( nWdt < nMinWdt ) + nWdt = nMinWdt; + if ( nWdt > nMaxWdt ) + nWdt = nMaxWdt; + nWdt += nHDist; + if ( nWdt < 1 ) + nWdt = 1; // nHDist kann auch negativ sein + if ( nHgt < nMinHgt ) + nHgt = nMinHgt; + if ( nHgt > nMaxHgt ) + nHgt = nMaxHgt; + nHgt+=nVDist; + if ( nHgt < 1 ) + nHgt = 1; // nVDist kann auch negativ sein + long nWdtGrow = nWdt-(rR.Right()-rR.Left()); + long nHgtGrow = nHgt-(rR.Bottom()-rR.Top()); + if ( nWdtGrow == 0 ) + bWdtGrow = FALSE; + if ( nHgtGrow == 0 ) + bHgtGrow=FALSE; + if ( bWdtGrow || bHgtGrow ) + { + if ( bWdtGrow ) + { + SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); + if ( eHAdj == SDRTEXTHORZADJUST_LEFT ) + rR.Right()+=nWdtGrow; + else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT ) + rR.Left()-=nWdtGrow; + else + { + long nWdtGrow2=nWdtGrow/2; + rR.Left()-=nWdtGrow2; + rR.Right()=rR.Left()+nWdt; + } + } + if ( bHgtGrow ) + { + SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); + if ( eVAdj == SDRTEXTVERTADJUST_TOP ) + rR.Bottom()+=nHgtGrow; + else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM ) + rR.Top()-=nHgtGrow; + else + { + long nHgtGrow2=nHgtGrow/2; + rR.Top()-=nHgtGrow2; + rR.Bottom()=rR.Top()+nHgt; + } + } + if ( aGeo.nDrehWink ) + { + Point aD1(rR.TopLeft()); + aD1-=aR0.TopLeft(); + Point aD2(aD1); + RotatePoint(aD2,Point(),aGeo.nSin,aGeo.nCos); + aD2-=aD1; + rR.Move(aD2.X(),aD2.Y()); + } + return TRUE; + } + } + } + return FALSE; +} + +Rectangle SdrObjCustomShape::ImpCalculateTextFrame( const FASTBOOL bHgt, const FASTBOOL bWdt ) +{ + Rectangle aReturnValue; + + Rectangle aOldTextRect( aRect ); // <- initial text rectangle + + Rectangle aNewTextRect( aRect ); // <- new text rectangle returned from the custom shape renderer, + GetTextBounds( aNewTextRect ); // it depends to the current logical shape size + + Rectangle aAdjustedTextRect( aNewTextRect ); // <- new text rectangle is being tested by AdjustTextFrameWidthAndHeight to ensure + if ( AdjustTextFrameWidthAndHeight( aAdjustedTextRect, bHgt, bWdt ) ) // that the new text rectangle is matching the current text size from the outliner + { + if ( ( aAdjustedTextRect != aNewTextRect ) && ( aOldTextRect != aAdjustedTextRect ) ) + { + aReturnValue = aRect; + double fXScale = (double)aOldTextRect.GetWidth() / (double)aNewTextRect.GetWidth(); + double fYScale = (double)aOldTextRect.GetHeight() / (double)aNewTextRect.GetHeight(); + double fRightDiff = (double)( aAdjustedTextRect.Right() - aNewTextRect.Right() ) * fXScale; + double fLeftDiff = (double)( aAdjustedTextRect.Left() - aNewTextRect.Left() ) * fXScale; + double fTopDiff = (double)( aAdjustedTextRect.Top() - aNewTextRect.Top() ) * fYScale; + double fBottomDiff= (double)( aAdjustedTextRect.Bottom()- aNewTextRect.Bottom()) * fYScale; + aReturnValue.Left() += (sal_Int32)fLeftDiff; + aReturnValue.Right() += (sal_Int32)fRightDiff; + aReturnValue.Top() += (sal_Int32)fTopDiff; + aReturnValue.Bottom() += (sal_Int32)fBottomDiff; + } + } + return aReturnValue; +} + +FASTBOOL SdrObjCustomShape::NbcAdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt) +{ + Rectangle aNewTextRect = ImpCalculateTextFrame( bHgt, bWdt ); + sal_Bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != aRect ); + if ( bRet ) + { + // taking care of handles that should not been changed + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + + aRect = aNewTextRect; + SetRectsDirty(); + SetChanged(); + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + try + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED ) + aIter->xInteraction->setControllerPosition( aIter->aPosition ); + } + catch ( const uno::RuntimeException& ) + { + } + aIter++; + } + InvalidateRenderGeometry(); + } + return bRet; +} +FASTBOOL SdrObjCustomShape::AdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt) +{ + Rectangle aNewTextRect = ImpCalculateTextFrame( bHgt, bWdt ); + sal_Bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != aRect ); + if ( bRet ) + { + Rectangle aBoundRect0; + if ( pUserCall ) + aBoundRect0 = GetCurrentBoundRect(); + + // taking care of handles that should not been changed + std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles( this ) ); + +// SendRepaintBroadcast(); + aRect = aNewTextRect; + SetRectsDirty(); + + std::vector< SdrCustomShapeInteraction >::iterator aIter( aInteractionHandles.begin() ); + while ( aIter != aInteractionHandles.end() ) + { + try + { + if ( aIter->nMode & CUSTOMSHAPE_HANDLE_RESIZE_FIXED ) + aIter->xInteraction->setControllerPosition( aIter->aPosition ); + } + catch ( const uno::RuntimeException& ) + { + } + aIter++; + } + + InvalidateRenderGeometry(); + SetChanged(); +// SendRepaintBroadcast(); + BroadcastObjectChange(); + SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); + } + return bRet; +} +sal_Bool SdrObjCustomShape::BegTextEdit( SdrOutliner& rOutl ) +{ + return SdrTextObj::BegTextEdit( rOutl ); +} +void SdrObjCustomShape::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const +{ + Size aPaperMin,aPaperMax; + Rectangle aViewInit; + TakeTextAnchorRect( aViewInit ); + if ( aGeo.nDrehWink ) + { + Point aCenter(aViewInit.Center()); + aCenter-=aViewInit.TopLeft(); + Point aCenter0(aCenter); + RotatePoint(aCenter,Point(),aGeo.nSin,aGeo.nCos); + aCenter-=aCenter0; + aViewInit.Move(aCenter.X(),aCenter.Y()); + } + Size aAnkSiz(aViewInit.GetSize()); + aAnkSiz.Width()--; aAnkSiz.Height()--; // weil GetSize() ein draufaddiert + Size aMaxSiz(1000000,1000000); + if (pModel!=NULL) { + Size aTmpSiz(pModel->GetMaxObjSize()); + if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width(); + if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height(); + } + SdrTextHorzAdjust eHAdj(GetTextHorizontalAdjust()); + SdrTextVertAdjust eVAdj(GetTextVerticalAdjust()); + + long nMinWdt = GetMinTextFrameWidth(); + long nMinHgt = GetMinTextFrameHeight(); + long nMaxWdt = GetMaxTextFrameWidth(); + long nMaxHgt = GetMaxTextFrameHeight(); + if (nMinWdt<1) nMinWdt=1; + if (nMinHgt<1) nMinHgt=1; + if ( nMaxWdt == 0 || nMaxWdt > aMaxSiz.Width() ) + nMaxWdt = aMaxSiz.Width(); + if ( nMaxHgt == 0 || nMaxHgt > aMaxSiz.Height() ) + nMaxHgt=aMaxSiz.Height(); + + if (((SdrTextWordWrapItem&)(GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue()) + { + if ( IsVerticalWriting() ) + { + nMaxHgt = aAnkSiz.Height(); + nMinHgt = nMaxHgt; + } + else + { + nMaxWdt = aAnkSiz.Width(); + nMinWdt = nMaxWdt; + } + } + aPaperMax.Width()=nMaxWdt; + aPaperMax.Height()=nMaxHgt; + + aPaperMin.Width()=nMinWdt; + aPaperMin.Height()=nMinHgt; + + if ( pViewMin ) + { + *pViewMin = aViewInit; + + long nXFree = aAnkSiz.Width() - aPaperMin.Width(); + if ( eHAdj == SDRTEXTHORZADJUST_LEFT ) + pViewMin->Right() -= nXFree; + else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT ) + pViewMin->Left() += nXFree; + else { pViewMin->Left() += nXFree / 2; pViewMin->Right() = pViewMin->Left() + aPaperMin.Width(); } + + long nYFree = aAnkSiz.Height() - aPaperMin.Height(); + if ( eVAdj == SDRTEXTVERTADJUST_TOP ) + pViewMin->Bottom() -= nYFree; + else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM ) + pViewMin->Top() += nYFree; + else { pViewMin->Top() += nYFree / 2; pViewMin->Bottom() = pViewMin->Top() + aPaperMin.Height(); } + } + + if( IsVerticalWriting() ) + aPaperMin.Width() = 0; + else + aPaperMin.Height() = 0; // #33102# + + if( eHAdj != SDRTEXTHORZADJUST_BLOCK ) + aPaperMin.Width()=0; + + // #103516# For complete ver adjust support, set paper min height to 0, here. + if(SDRTEXTVERTADJUST_BLOCK != eVAdj ) + aPaperMin.Height() = 0; + + if (pPaperMin!=NULL) *pPaperMin=aPaperMin; + if (pPaperMax!=NULL) *pPaperMax=aPaperMax; + if (pViewInit!=NULL) *pViewInit=aViewInit; +} +void SdrObjCustomShape::EndTextEdit( SdrOutliner& rOutl ) +{ + SdrTextObj::EndTextEdit( rOutl ); + InvalidateRenderGeometry(); +} +void SdrObjCustomShape::TakeTextAnchorRect( Rectangle& rAnchorRect ) const +{ + if ( GetTextBounds( rAnchorRect ) ) + { + Point aRotateRef( maSnapRect.Center() ); + rAnchorRect.Left() += GetTextLeftDistance(); + rAnchorRect.Top() += GetTextUpperDistance(); + rAnchorRect.Right() -= GetTextRightDistance(); + rAnchorRect.Bottom() -= GetTextLowerDistance(); + ImpJustifyRect( rAnchorRect ); + + if ( rAnchorRect.GetWidth() < 2 ) + rAnchorRect.Right() = rAnchorRect.Left() + 1; // minimal width is 2 + if ( rAnchorRect.GetHeight() < 2 ) + rAnchorRect.Bottom() = rAnchorRect.Top() + 1; // minimal height is 2 + if ( aGeo.nDrehWink ) + { + Point aP( rAnchorRect.TopLeft() ); + RotatePoint( aP, aRotateRef, aGeo.nSin, aGeo. nCos ); + rAnchorRect.SetPos( aP ); + } + } + else + SdrTextObj::TakeTextAnchorRect( rAnchorRect ); +} +void SdrObjCustomShape::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, FASTBOOL bNoEditText, + Rectangle* pAnchorRect, BOOL /*bLineWidth*/) const +{ + Rectangle aAnkRect; // Rect innerhalb dem geankert wird + TakeTextAnchorRect(aAnkRect); + SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); + SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); + ULONG nStat0=rOutliner.GetControlWord(); + Size aNullSize; + + rOutliner.SetControlWord(nStat0|EE_CNTRL_AUTOPAGESIZE); + rOutliner.SetMinAutoPaperSize(aNullSize); + sal_Int32 nMaxAutoPaperWidth = 1000000; + sal_Int32 nMaxAutoPaperHeight= 1000000; + + long nAnkWdt=aAnkRect.GetWidth(); + long nAnkHgt=aAnkRect.GetHeight(); + + if (((SdrTextWordWrapItem&)(GetMergedItem(SDRATTR_TEXT_WORDWRAP))).GetValue()) + { + if ( IsVerticalWriting() ) + nMaxAutoPaperHeight = nAnkHgt; + else + nMaxAutoPaperWidth = nAnkWdt; + } + if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting()) + { + rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0)); + } + + if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting()) + { + rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt)); + } + rOutliner.SetMaxAutoPaperSize( Size( nMaxAutoPaperWidth, nMaxAutoPaperHeight ) ); + rOutliner.SetPaperSize( aNullSize ); + + // Text in den Outliner stecken - ggf. den aus dem EditOutliner + OutlinerParaObject* pPara= GetOutlinerParaObject(); + if (pEdtOutl && !bNoEditText) + pPara=pEdtOutl->CreateParaObject(); + + if (pPara) + { + BOOL bHitTest = FALSE; + if( pModel ) + bHitTest = &pModel->GetHitTestOutliner() == &rOutliner; + + const SdrTextObj* pTestObj = rOutliner.GetTextObj(); + if( !pTestObj || !bHitTest || pTestObj != this || + pTestObj->GetOutlinerParaObject() != GetOutlinerParaObject() ) + { + if( bHitTest ) + rOutliner.SetTextObj( this ); + + rOutliner.SetUpdateMode(TRUE); + rOutliner.SetText(*pPara); + } + } + else + { + rOutliner.SetTextObj( NULL ); + } + if (pEdtOutl && !bNoEditText && pPara) + delete pPara; + + rOutliner.SetUpdateMode(TRUE); + rOutliner.SetControlWord(nStat0); + + SdrText* pText = getActiveText(); + if( pText ) + pText->CheckPortionInfo( rOutliner ); + + Point aTextPos(aAnkRect.TopLeft()); + Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() hat etwas Toleranz drauf, oder? + + // #106653# + // For draw objects containing text correct hor/ver alignment if text is bigger + // than the object itself. Without that correction, the text would always be + // formatted to the left edge (or top edge when vertical) of the draw object. + + if( !IsTextFrame() ) + { + if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting()) + { + // #110129# + // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK, + // else the alignment is wanted. + if(SDRTEXTHORZADJUST_BLOCK == eHAdj) + { + eHAdj = SDRTEXTHORZADJUST_CENTER; + } + } + + if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting()) + { + // #110129# + // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK, + // else the alignment is wanted. + if(SDRTEXTVERTADJUST_BLOCK == eVAdj) + { + eVAdj = SDRTEXTVERTADJUST_CENTER; + } + } + } + + if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT) + { + long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width(); + if (eHAdj==SDRTEXTHORZADJUST_CENTER) + aTextPos.X()+=nFreeWdt/2; + if (eHAdj==SDRTEXTHORZADJUST_RIGHT) + aTextPos.X()+=nFreeWdt; + } + if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM) + { + long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height(); + if (eVAdj==SDRTEXTVERTADJUST_CENTER) + aTextPos.Y()+=nFreeHgt/2; + if (eVAdj==SDRTEXTVERTADJUST_BOTTOM) + aTextPos.Y()+=nFreeHgt; + } + if (aGeo.nDrehWink!=0) + RotatePoint(aTextPos,aAnkRect.TopLeft(),aGeo.nSin,aGeo.nCos); + + if (pAnchorRect) + *pAnchorRect=aAnkRect; + + // rTextRect ist bei ContourFrame in einigen Faellen nicht korrekt + rTextRect=Rectangle(aTextPos,aTextSiz); +} + +void SdrObjCustomShape::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject) +{ + SdrTextObj::NbcSetOutlinerParaObject( pTextObject ); + SetBoundRectDirty(); + SetRectsDirty(TRUE); + InvalidateRenderGeometry(); +} + +void SdrObjCustomShape::operator=(const SdrObject& rObj) +{ + SdrTextObj::operator=( rObj ); + aName =((SdrObjCustomShape&)rObj).aName; + fObjectRotation = ((SdrObjCustomShape&)rObj).fObjectRotation; + InvalidateRenderGeometry(); +} + + +void SdrObjCustomShape::TakeObjNameSingul(XubString& rName) const +{ + rName = ImpGetResStr(STR_ObjNameSingulCUSTOMSHAPE); + String aNm( GetName() ); + if( aNm.Len() ) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aNm; + rName += sal_Unicode('\''); + } +} + +void SdrObjCustomShape::TakeObjNamePlural(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNamePluralCUSTOMSHAPE); +} + +basegfx::B2DPolyPolygon SdrObjCustomShape::TakeXorPoly() const +{ + return GetLineGeometry( (SdrObjCustomShape*)this, sal_False ); +} + +basegfx::B2DPolyPolygon SdrObjCustomShape::TakeContour() const +{ + const SdrObject* pSdrObject = GetSdrObjectFromCustomShape(); + if ( pSdrObject ) + return pSdrObject->TakeContour(); + return basegfx::B2DPolyPolygon(); +} + +SdrObject* SdrObjCustomShape::DoConvertToPolyObj(BOOL bBezier) const +{ + // #i37011# + SdrObject* pRetval = 0L; + SdrObject* pRenderedCustomShape = 0L; + + if ( !mXRenderedCustomShape.is() ) + { + // force CustomShape + ((SdrObjCustomShape*)this)->GetSdrObjectFromCustomShape(); + } + + if ( mXRenderedCustomShape.is() ) + { + pRenderedCustomShape = GetSdrObjectFromXShape( mXRenderedCustomShape ); + } + + if ( pRenderedCustomShape ) + { + SdrObject* pCandidate = pRenderedCustomShape->Clone(); + DBG_ASSERT(pCandidate, "SdrObjCustomShape::DoConvertToPolyObj: Could not clone SdrObject (!)"); + pCandidate->SetModel(GetModel()); + pRetval = pCandidate->DoConvertToPolyObj(bBezier); + SdrObject::Free( pCandidate ); + + if(pRetval) + { + const sal_Bool bShadow(((SdrShadowItem&)GetMergedItem(SDRATTR_SHADOW)).GetValue()); + if(bShadow) + { + pRetval->SetMergedItem(SdrShadowItem(sal_True)); + } + } + + if(HasText() && !IsTextPath()) + { + pRetval = ImpConvertAddText(pRetval, bBezier); + } + } + + return pRetval; +} + +void SdrObjCustomShape::NbcSetStyleSheet( SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr ) +{ + // #i40944# + InvalidateRenderGeometry(); + SdrObject::NbcSetStyleSheet( pNewStyleSheet, bDontRemoveHardAttr ); +} + +void SdrObjCustomShape::SetPage( SdrPage* pNewPage ) +{ + SdrTextObj::SetPage( pNewPage ); + + if( pNewPage ) + { + // invalidating rectangles by SetRectsDirty is not sufficient, + // AdjustTextFrameWidthAndHeight() also has to be made, both + // actions are done by NbcSetSnapRect + Rectangle aTmp( aRect ); //creating temporary rectangle #i61108# + NbcSetSnapRect( aTmp ); + } +} + +SdrObjGeoData* SdrObjCustomShape::NewGeoData() const +{ + return new SdrAShapeObjGeoData; +} + +void SdrObjCustomShape::SaveGeoData(SdrObjGeoData& rGeo) const +{ + SdrTextObj::SaveGeoData( rGeo ); + SdrAShapeObjGeoData& rAGeo=(SdrAShapeObjGeoData&)rGeo; + rAGeo.fObjectRotation = fObjectRotation; + rAGeo.bMirroredX = IsMirroredX(); + rAGeo.bMirroredY = IsMirroredY(); + + const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) ); + Any* pAny( ( (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ).GetPropertyValueByName( sAdjustmentValues ) ); + if ( pAny ) + *pAny >>= rAGeo.aAdjustmentSeq; +} + +void SdrObjCustomShape::RestGeoData(const SdrObjGeoData& rGeo) +{ + SdrTextObj::RestGeoData( rGeo ); + SdrAShapeObjGeoData& rAGeo=(SdrAShapeObjGeoData&)rGeo; + fObjectRotation = rAGeo.fObjectRotation; + SetMirroredX( rAGeo.bMirroredX ); + SetMirroredY( rAGeo.bMirroredY ); + + SdrCustomShapeGeometryItem rGeometryItem = (SdrCustomShapeGeometryItem&)GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); + const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) ); + PropertyValue aPropVal; + aPropVal.Name = sAdjustmentValues; + aPropVal.Value <<= rAGeo.aAdjustmentSeq; + rGeometryItem.SetPropertyValue( aPropVal ); + SetMergedItem( rGeometryItem ); + + InvalidateRenderGeometry(); +} + +void SdrObjCustomShape::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/) +{ + // break up matrix + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate, fShearX; + rMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + + // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings + // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly + if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) + { + aScale.setX(fabs(aScale.getX())); + aScale.setY(fabs(aScale.getY())); + fRotate = fmod(fRotate + F_PI, F_2PI); + } + + // reset object shear and rotations + aGeo.nDrehWink = 0; + aGeo.RecalcSinCos(); + aGeo.nShearWink = 0; + aGeo.RecalcTan(); + + // force metric to pool metric + SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // position + aTranslate.setX(ImplMMToTwips(aTranslate.getX())); + aTranslate.setY(ImplMMToTwips(aTranslate.getY())); + + // size + aScale.setX(ImplMMToTwips(aScale.getX())); + aScale.setY(ImplMMToTwips(aScale.getY())); + + break; + } + default: + { + DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!"); + } + } + } + + // if anchor is used, make position relative to it + if( pModel && pModel->IsWriter() ) + { + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // build and set BaseRect (use scale) + Point aPoint = Point(); + Size aSize(FRound(aScale.getX()), FRound(aScale.getY())); + Rectangle aBaseRect(aPoint, aSize); + SetSnapRect(aBaseRect); + + // shear? + if(!basegfx::fTools::equalZero(fShearX)) + { + GeoStat aGeoStat; + aGeoStat.nShearWink = FRound((atan(fShearX) / F_PI180) * 100.0); + aGeoStat.RecalcTan(); + Shear(Point(), aGeoStat.nShearWink, aGeoStat.nTan, FALSE); + } + + // rotation? + if(!basegfx::fTools::equalZero(fRotate)) + { + GeoStat aGeoStat; + + // #i78696# + // fRotate is mathematically correct, but aGeoStat.nDrehWink is + // mirrored -> mirror value here + aGeoStat.nDrehWink = NormAngle360(FRound(-fRotate / F_PI18000)); + aGeoStat.RecalcSinCos(); + Rotate(Point(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos); + } + + // translate? + if(!aTranslate.equalZero()) + { + Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY()))); + } +} + +// taking fObjectRotation instead of aGeo.nWink +sal_Bool SdrObjCustomShape::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const +{ + // get turn and shear +// double fRotate = (aGeo.nDrehWink / 100.0) * F_PI180; + double fRotate = fObjectRotation * F_PI180; + double fShearX = (aGeo.nShearWink / 100.0) * F_PI180; + + // get aRect, this is the unrotated snaprect + Rectangle aRectangle(aRect); + + sal_Bool bMirroredX = IsMirroredX(); + sal_Bool bMirroredY = IsMirroredY(); + if ( bMirroredX || bMirroredY ) + { // we have to retrieve the unmirrored rect + + GeoStat aNewGeo( aGeo ); + + if ( bMirroredX ) + { + Polygon aPol( Rect2Poly( aRect, aNewGeo ) ); + Rectangle aBoundRect( aPol.GetBoundRect() ); + + Point aRef1( ( aBoundRect.Left() + aBoundRect.Right() ) >> 1, aBoundRect.Top() ); + Point aRef2( aRef1.X(), aRef1.Y() + 1000 ); + USHORT i; + USHORT nPntAnz=aPol.GetSize(); + for (i=0; i<nPntAnz; i++) + { + MirrorPoint(aPol[i],aRef1,aRef2); + } + // Polygon wenden und etwas schieben + Polygon aPol0(aPol); + aPol[0]=aPol0[1]; + aPol[1]=aPol0[0]; + aPol[2]=aPol0[3]; + aPol[3]=aPol0[2]; + aPol[4]=aPol0[1]; + Poly2Rect(aPol,aRectangle,aNewGeo); + } + if ( bMirroredY ) + { + Polygon aPol( Rect2Poly( aRectangle, aNewGeo ) ); + Rectangle aBoundRect( aPol.GetBoundRect() ); + + Point aRef1( aBoundRect.Left(), ( aBoundRect.Top() + aBoundRect.Bottom() ) >> 1 ); + Point aRef2( aRef1.X() + 1000, aRef1.Y() ); + USHORT i; + USHORT nPntAnz=aPol.GetSize(); + for (i=0; i<nPntAnz; i++) + { + MirrorPoint(aPol[i],aRef1,aRef2); + } + // Polygon wenden und etwas schieben + Polygon aPol0(aPol); + aPol[0]=aPol0[1]; + aPol[1]=aPol0[0]; + aPol[2]=aPol0[3]; + aPol[3]=aPol0[2]; + aPol[4]=aPol0[1]; + Poly2Rect(aPol,aRectangle,aNewGeo); + } + } + + // fill other values + basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight()); + basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top()); + + // position maybe relative to anchorpos, convert + if( pModel && pModel->IsWriter() ) + { + if(GetAnchorPos().X() || GetAnchorPos().Y()) + { + aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); + } + } + + // force MapUnit to 100th mm + SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->GetMetric(0); + if(eMapUnit != SFX_MAPUNIT_100TH_MM) + { + switch(eMapUnit) + { + case SFX_MAPUNIT_TWIP : + { + // postion + aTranslate.setX(ImplTwipsToMM(aTranslate.getX())); + aTranslate.setY(ImplTwipsToMM(aTranslate.getY())); + + // size + aScale.setX(ImplTwipsToMM(aScale.getX())); + aScale.setY(ImplTwipsToMM(aScale.getY())); + + break; + } + default: + { + DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!"); + } + } + } + + // build matrix + rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + aScale, + basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX), + basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate, + aTranslate); + + return sal_False; +} + +sdr::contact::ViewContact* SdrObjCustomShape::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfSdrObjCustomShape(*this); +} + +// #i33136# +bool SdrObjCustomShape::doConstructOrthogonal(const ::rtl::OUString& rName) +{ + bool bRetval(false); + static ::rtl::OUString Imps_sNameASOrtho_quadrat( RTL_CONSTASCII_USTRINGPARAM( "quadrat" ) ); + static ::rtl::OUString Imps_sNameASOrtho_round_quadrat( RTL_CONSTASCII_USTRINGPARAM( "round-quadrat" ) ); + static ::rtl::OUString Imps_sNameASOrtho_circle( RTL_CONSTASCII_USTRINGPARAM( "circle" ) ); + static ::rtl::OUString Imps_sNameASOrtho_circle_pie( RTL_CONSTASCII_USTRINGPARAM( "circle-pie" ) ); + static ::rtl::OUString Imps_sNameASOrtho_ring( RTL_CONSTASCII_USTRINGPARAM( "ring" ) ); + + if(Imps_sNameASOrtho_quadrat.equalsIgnoreAsciiCase(rName)) + { + bRetval = true; + } + else if(Imps_sNameASOrtho_round_quadrat.equalsIgnoreAsciiCase(rName)) + { + bRetval = true; + } + else if(Imps_sNameASOrtho_circle.equalsIgnoreAsciiCase(rName)) + { + bRetval = true; + } + else if(Imps_sNameASOrtho_circle_pie.equalsIgnoreAsciiCase(rName)) + { + bRetval = true; + } + else if(Imps_sNameASOrtho_ring.equalsIgnoreAsciiCase(rName)) + { + bRetval = true; + } + + return bRetval; +} + +// #i37011# centralize throw-away of render geometry +void SdrObjCustomShape::InvalidateRenderGeometry() +{ + mXRenderedCustomShape = 0L; + SdrObject::Free( mpLastShadowGeometry ); + mpLastShadowGeometry = 0L; +} + +// eof |