/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <com/sun/star/lang/XComponent.hpp>

#define _USE_MATH_DEFINES
#include <math.h>
#include <vcl/metaact.hxx>   // fuer TakeContour
#include <vcl/cvtsvm.hxx>
#include <tools/line.hxx>
#include <tools/bigint.hxx>
#include <tools/diagnose_ex.h>
#include <vector>
#include <svx/svdobj.hxx>
#include <svx/xpoly.hxx>
#include <svx/svdetc.hxx>
#include <svx/svdtrans.hxx>
#include <svx/svdhdl.hxx>
#include <svx/svddrag.hxx>
#include <svx/svdmodel.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdovirt.hxx>  // Fuer Add/Del Ref
#include <svx/svdview.hxx>   // fuer Dragging (Ortho abfragen)
#include "svx/svdglob.hxx"   // StringCache
#include <svx/svdstr.hrc>    // Objektname
#include <svx/svdogrp.hxx>   // Factory
#include <svx/svdopath.hxx>  // Factory
#include <svx/svdoedge.hxx>  // Factory
#include <svx/svdorect.hxx>  // Factory
#include <svx/svdocirc.hxx>  // Factory
#include <svx/svdotext.hxx>  // Factory
#include <svx/svdomeas.hxx>  // Factory
#include <svx/svdograf.hxx>  // Factory
#include <svx/svdoole2.hxx>  // Factory
#include <svx/svdocapt.hxx>  // Factory
#include <svx/svdopage.hxx>  // Factory
#include <svx/svdouno.hxx>   // Factory
#include <svx/svdattrx.hxx> // NotPersistItems
#include <svx/svdoashp.hxx>
#include <svx/svdomedia.hxx>
#include <svx/xlnwtit.hxx>
#include <svx/xlnstwit.hxx>
#include <svx/xlnedwit.hxx>
#include <svx/xlnstit.hxx>
#include <svx/xlnedit.hxx>
#include <svx/xlnstcit.hxx>
#include <svx/xlnedcit.hxx>
#include <svx/xlndsit.hxx>
#include <svx/xlnclit.hxx>
#include <svx/xflclit.hxx>
#include <svx/svditer.hxx>
#include <svx/xlntrit.hxx>
#include <svx/xfltrit.hxx>
#include <svx/xfltrit.hxx>
#include <svx/xflftrit.hxx>
#include "svx/xlinjoit.hxx"
#include <svx/unopage.hxx>
#include <editeng/eeitem.hxx>
#include <svx/xenum.hxx>
#include <svx/xgrad.hxx>
#include <svx/xhatch.hxx>
#include <svx/xflhtit.hxx>
#include <svx/xbtmpit.hxx>
#include <svx/svdpool.hxx>
#include <editeng/editeng.hxx>
#include <vcl/salbtype.hxx>		// FRound
#include <svl/whiter.hxx>

// #97849#
#include <svx/fmmodel.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/objface.hxx>
#include "svdoimp.hxx"
#include <vcl/graphictools.hxx>
#include <svtools/colorcfg.hxx>
#include <svx/sdr/properties/emptyproperties.hxx>
#include <svx/sdr/contact/viewcontactofsdrobj.hxx>
#include <svx/sdr/contact/viewcontactofgraphic.hxx>
#include <svx/sdr/contact/objectcontactofobjlistpainter.hxx>
#include <svx/sdr/contact/displayinfo.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/range/b2drange.hxx>
#include <svx/unoshape.hxx>
#include <vcl/virdev.hxx>
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
#include <drawinglayer/processor2d/contourextractor2d.hxx>
#include <drawinglayer/processor2d/linegeometryextractor2d.hxx>
#include <svx/polysc3d.hxx>
#include "svx/svdotable.hxx"
#include "svx/shapepropertynotifier.hxx"
#include <svx/sdrhittesthelper.hxx>
#include <svx/svdundo.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <svx/sdrobjectfilter.hxx>

using namespace ::com::sun::star;

// #104018# replace macros above with type-detecting methods
inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); }
inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); }

////////////////////////////////////////////////////////////////////////////////////////////////////

TYPEINIT0(SdrObjUserCall);

SdrObjUserCall::~SdrObjUserCall()
{
}

void SdrObjUserCall::Changed(const SdrObject& /*rObj*/, SdrUserCallType /*eType*/, const Rectangle& /*rOldBoundRect*/)
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////

TYPEINIT0(SdrObjUserData);

void SdrObjUserData::operator=(const SdrObjUserData& /*rData*/)    // nicht implementiert
{
}

sal_Bool SdrObjUserData::operator==(const SdrObjUserData& /*rData*/) const // nicht implementiert
{
	return sal_False;
}

sal_Bool SdrObjUserData::operator!=(const SdrObjUserData& /*rData*/) const // nicht implementiert
{
	return sal_False;
}

SdrObjUserData::~SdrObjUserData()
{
}

FASTBOOL SdrObjUserData::HasMacro(const SdrObject* /*pObj*/) const
{
	return sal_False;
}

SdrObject* SdrObjUserData::CheckMacroHit(const SdrObjMacroHitRec& rRec, const SdrObject* pObj) const
{
	if(pObj)
    {
        if(rRec.pPageView)
        {
    	    return SdrObjectPrimitiveHit(*pObj, rRec.aPos, rRec.nTol, *rRec.pPageView, rRec.pVisiLayer, false);
        }
    }

	return 0;
}

Pointer SdrObjUserData::GetMacroPointer(const SdrObjMacroHitRec& /*rRec*/, const SdrObject* /*pObj*/) const
{
	return Pointer(POINTER_REFHAND);
}

void SdrObjUserData::PaintMacro(OutputDevice& rOut, const Rectangle& /*rDirtyRect*/, const SdrObjMacroHitRec& /*rRec*/, const SdrObject* pObj) const
{
	if(!pObj)
        return;

	const RasterOp eRop(rOut.GetRasterOp());
	const basegfx::B2DPolyPolygon aPolyPolygon(pObj->TakeXorPoly());
	const sal_uInt32 nCount(aPolyPolygon.count());

    rOut.SetLineColor(COL_BLACK);
    rOut.SetFillColor();
	rOut.SetRasterOp(ROP_INVERT);

	for(sal_uInt32 a(0); a < nCount; a++)
	{
		rOut.DrawPolyLine(aPolyPolygon.getB2DPolygon(a));
	}

    rOut.SetRasterOp(eRop);
}

FASTBOOL SdrObjUserData::DoMacro(const SdrObjMacroHitRec& /*rRec*/, SdrObject* /*pObj*/)
{
	return sal_False;
}

XubString SdrObjUserData::GetMacroPopupComment(const SdrObjMacroHitRec& /*rRec*/, const SdrObject* /*pObj*/) const
{
	return String();
}

void SdrObjUserDataList::Clear()
{
	sal_uInt16 nAnz=GetUserDataCount();
	for (sal_uInt16 i=0; i<nAnz; i++) {
		delete GetUserData(i);
	}
	aList.Clear();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

DBG_NAME(SdrObjGeoData);

SdrObjGeoData::SdrObjGeoData():
	pGPL(NULL),
	bMovProt(sal_False),
	bSizProt(sal_False),
	bNoPrint(sal_False),
	bClosedObj(sal_False),
	mbVisible(true),
	mnLayerID(0)
{
	DBG_CTOR(SdrObjGeoData,NULL);
}

SdrObjGeoData::~SdrObjGeoData()
{
	DBG_DTOR(SdrObjGeoData,NULL);
	delete pGPL;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

TYPEINIT0(SdrObjPlusData);

SdrObjPlusData::SdrObjPlusData():
	pBroadcast(NULL),
	pUserDataList(NULL),
	pGluePoints(NULL),
	pAutoTimer(NULL)
{
}

SdrObjPlusData::~SdrObjPlusData()
{
	if (pBroadcast   !=NULL) delete pBroadcast;
	if (pUserDataList!=NULL) delete pUserDataList;
	if (pGluePoints  !=NULL) delete pGluePoints;
	if (pAutoTimer   !=NULL) delete pAutoTimer;
}

SdrObjPlusData* SdrObjPlusData::Clone(SdrObject* pObj1) const
{
	SdrObjPlusData* pNeuPlusData=new SdrObjPlusData;
	if (pUserDataList!=NULL) {
		sal_uInt16 nAnz=pUserDataList->GetUserDataCount();
		if (nAnz!=0) {
			pNeuPlusData->pUserDataList=new SdrObjUserDataList;
			for (sal_uInt16 i=0; i<nAnz; i++) {
				SdrObjUserData* pNeuUserData=pUserDataList->GetUserData(i)->Clone(pObj1);
				if (pNeuUserData!=NULL) {
					pNeuPlusData->pUserDataList->InsertUserData(pNeuUserData);
				} else {
					DBG_ERROR("SdrObjPlusData::Clone(): UserData.Clone() liefert NULL");
				}
			}
		}
	}
	if (pGluePoints!=NULL) pNeuPlusData->pGluePoints=new SdrGluePointList(*pGluePoints);
	// MtfAnimator wird auch nicht mitkopiert

	// #i68101#
	// copy object name, title and description
	pNeuPlusData->aObjName = aObjName;
	pNeuPlusData->aObjTitle = aObjTitle;
	pNeuPlusData->aObjDescription = aObjDescription;

	if (pAutoTimer!=NULL) {
		pNeuPlusData->pAutoTimer=new AutoTimer;
		// Handler, etc. nicht mitkopieren!
	}

	// For HTMLName: Do not clone, leave uninitialized (empty string)

	return pNeuPlusData;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
//
//   @@@@  @@@@@  @@@@@@ @@@@@  @@@@  @@@@@@
//  @@  @@ @@  @@     @@ @@    @@  @@   @@
//  @@  @@ @@  @@     @@ @@    @@       @@
//  @@  @@ @@@@@      @@ @@@@  @@       @@
//  @@  @@ @@  @@     @@ @@    @@       @@
//  @@  @@ @@  @@ @@  @@ @@    @@  @@   @@
//   @@@@  @@@@@   @@@@  @@@@@  @@@@    @@
//
////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
// BaseProperties section

sdr::properties::BaseProperties* SdrObject::CreateObjectSpecificProperties()
{
	return new sdr::properties::EmptyProperties(*this);
}

sdr::properties::BaseProperties& SdrObject::GetProperties() const
{
	if(!mpProperties)
	{
		const_cast< SdrObject* >(this)->mpProperties =
            const_cast< SdrObject* >(this)->CreateObjectSpecificProperties();
	}

	return *mpProperties;
}

//////////////////////////////////////////////////////////////////////////////
// ObjectUser section

void SdrObject::AddObjectUser(sdr::ObjectUser& rNewUser)
{
	maObjectUsers.push_back(&rNewUser);
}

void SdrObject::RemoveObjectUser(sdr::ObjectUser& rOldUser)
{
	const ::sdr::ObjectUserVector::iterator aFindResult = ::std::find(maObjectUsers.begin(), maObjectUsers.end(), &rOldUser);
	if(aFindResult != maObjectUsers.end())
	{
		maObjectUsers.erase(aFindResult);
	}
}

//////////////////////////////////////////////////////////////////////////////
// #110094# DrawContact section

sdr::contact::ViewContact* SdrObject::CreateObjectSpecificViewContact()
{
	return new sdr::contact::ViewContactOfSdrObj(*this);
}

sdr::contact::ViewContact& SdrObject::GetViewContact() const
{
	if(!mpViewContact)
	{
		const_cast< SdrObject* >(this)->mpViewContact =
            const_cast< SdrObject* >(this)->CreateObjectSpecificViewContact();
	}

	return *mpViewContact;
}

// DrawContact support: Methods for handling Object changes
void SdrObject::ActionChanged() const
{
    // Do necessary ViewContact actions
	GetViewContact().ActionChanged();
}

//////////////////////////////////////////////////////////////////////////////

void SdrObject::SetBoundRectDirty()
{
	aOutRect = Rectangle();
}

//////////////////////////////////////////////////////////////////////////////

DBG_NAME(SdrObject);
TYPEINIT1(SdrObject,SfxListener);

SdrObject::SdrObject()
    :mpProperties(0L)
    ,mpViewContact(0L)
    ,pObjList(NULL)
    ,pPage(NULL)
    ,pModel(NULL)
    ,pUserCall(NULL)
    ,pPlusData(NULL)
    ,nOrdNum(0)
    ,mnNavigationPosition(SAL_MAX_UINT32)
    ,mnLayerID(0)
    ,mpSvxShape( NULL )
    ,maWeakUnoShape()
{
	DBG_CTOR(SdrObject,NULL);
	bVirtObj         =sal_False;
	bSnapRectDirty   =sal_True;
	bNetLock         =sal_False;
	bInserted        =sal_False;
	bGrouped         =sal_False;
	bMovProt         =sal_False;
	bSizProt         =sal_False;
	bNoPrint         =sal_False;
	bEmptyPresObj    =sal_False;
	bNotVisibleAsMaster=sal_False;
	bClosedObj       =sal_False;
	mbVisible		 = true;

	// #i25616#
	mbLineIsOutsideGeometry = sal_False;

	// #i25616#
	mbSupportTextIndentingOnLineWidthChange = sal_False;

	//#110094#-1
	//bWriterFlyFrame  =sal_False;

	bNotMasterCachable=sal_False;
	bIsEdge=sal_False;
	bIs3DObj=sal_False;
	bMarkProt=sal_False;
	bIsUnoObj=sal_False;
}

SdrObject::~SdrObject()
{
	// tell all the registered ObjectUsers that the page is in destruction
	::sdr::ObjectUserVector aListCopy(maObjectUsers.begin(), maObjectUsers.end());
	for(::sdr::ObjectUserVector::iterator aIterator = aListCopy.begin(); aIterator != aListCopy.end(); aIterator++)
	{
		sdr::ObjectUser* pObjectUser = *aIterator;
		DBG_ASSERT(pObjectUser, "SdrObject::~SdrObject: corrupt ObjectUser list (!)");
		pObjectUser->ObjectInDestruction(*this);
	}

	// Clear the vector. This means that user do not need to call RemoveObjectUser()
	// when they get called from ObjectInDestruction().
	maObjectUsers.clear();

    try
    {
        SvxShape* pSvxShape = getSvxShape();
        if ( pSvxShape )
        {
            OSL_ENSURE(!pSvxShape->HasSdrObjectOwnership(),"Please check where this call come from and replace it with SdrObject::Free");
            pSvxShape->InvalidateSdrObject();
	        uno::Reference< lang::XComponent > xShapeComp( getWeakUnoShape(), uno::UNO_QUERY_THROW );
		    xShapeComp->dispose();
        }
    }
    catch( const uno::Exception& )
    {
    	DBG_UNHANDLED_EXCEPTION();
    }

	DBG_DTOR(SdrObject,NULL);
	SendUserCall(SDRUSERCALL_DELETE, GetLastBoundRect());
	if (pPlusData!=NULL) delete pPlusData;

	if(mpProperties)
	{
		delete mpProperties;
		mpProperties = 0L;
	}

	// #110094#
	if(mpViewContact)
	{
		delete mpViewContact;
		mpViewContact = 0L;
	}
}

void SdrObject::Free( SdrObject*& _rpObject )
{
    SdrObject* pObject = _rpObject; _rpObject = NULL;
    if ( pObject == NULL )
        // nothing to do
        return;

	SvxShape* pShape = pObject->getSvxShape();
    if ( pShape && pShape->HasSdrObjectOwnership() )
        // only the shape is allowed to delete me, and will reset the ownership before doing so
        return;

    delete pObject;
}

SdrObjPlusData* SdrObject::NewPlusData() const
{
	return new SdrObjPlusData;
}

void SdrObject::SetRectsDirty(sal_Bool bNotMyself)
{
	if (!bNotMyself) {
		SetBoundRectDirty();
		bSnapRectDirty=sal_True;
	}
	if (pObjList!=NULL) {
		pObjList->SetRectsDirty();
	}
}

void SdrObject::SetModel(SdrModel* pNewModel)
{
	if(pNewModel && pPage)
	{
		if(pPage->GetModel() != pNewModel)
		{
			pPage = NULL;
		}
	}

	// update listeners at possible api wrapper object
	if( pModel != pNewModel )
	{
		SvxShape* pShape = getSvxShape();
		if( pShape )
			pShape->ChangeModel( pNewModel );
	}

	pModel = pNewModel;
}

void SdrObject::SetObjList(SdrObjList* pNewObjList)
{
	pObjList=pNewObjList;
}

void SdrObject::SetPage(SdrPage* pNewPage)
{
	pPage=pNewPage;
	if (pPage!=NULL) {
		SdrModel* pMod=pPage->GetModel();
		if (pMod!=pModel && pMod!=NULL) {
			SetModel(pMod);
		}}
}

// init global static itempool
SdrItemPool* SdrObject::mpGlobalItemPool = NULL;

SdrItemPool& SdrObject::GetGlobalDrawObjectItemPool()
{
	if(!mpGlobalItemPool)
	{
		mpGlobalItemPool = new SdrItemPool();
		SfxItemPool* pGlobalOutlPool = EditEngine::CreatePool();
		mpGlobalItemPool->SetSecondaryPool(pGlobalOutlPool);
		mpGlobalItemPool->SetDefaultMetric((SfxMapUnit)SdrEngineDefaults::GetMapUnit());
		mpGlobalItemPool->FreezeIdRanges();
	}

	return *mpGlobalItemPool;
}

void SdrObject::FreeGlobalDrawObjectItemPool()
{
	// code for deletion of GlobalItemPool
	if(mpGlobalItemPool)
	{
		SfxItemPool* pGlobalOutlPool = mpGlobalItemPool->GetSecondaryPool();
        SfxItemPool::Free(mpGlobalItemPool);
        SfxItemPool::Free(pGlobalOutlPool);
	}
}

SdrItemPool* SdrObject::GetObjectItemPool() const
{
	if(pModel)
		return (SdrItemPool*)(&pModel->GetItemPool());

	// use a static global default pool
	return &SdrObject::GetGlobalDrawObjectItemPool();
}

sal_uInt32 SdrObject::GetObjInventor()   const
{
	return SdrInventor;
}

sal_uInt16 SdrObject::GetObjIdentifier() const
{
	return sal_uInt16(OBJ_NONE);
}

void SdrObject::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
{
	rInfo.bRotateFreeAllowed=sal_False;
	rInfo.bMirrorFreeAllowed=sal_False;
	rInfo.bTransparenceAllowed = sal_False;
	rInfo.bGradientAllowed = sal_False;
	rInfo.bShearAllowed     =sal_False;
	rInfo.bEdgeRadiusAllowed=sal_False;
	rInfo.bCanConvToPath    =sal_False;
	rInfo.bCanConvToPoly    =sal_False;
	rInfo.bCanConvToContour = sal_False;
	rInfo.bCanConvToPathLineToArea=sal_False;
	rInfo.bCanConvToPolyLineToArea=sal_False;
}

SdrLayerID SdrObject::GetLayer() const
{
	return mnLayerID;
}

void SdrObject::getMergedHierarchyLayerSet(SetOfByte& rSet) const
{
	rSet.Set(GetLayer());
	SdrObjList* pOL=GetSubList();
	if (pOL!=NULL) {
		sal_uIntPtr nObjAnz=pOL->GetObjCount();
		for (sal_uIntPtr nObjNum=0; nObjNum<nObjAnz; nObjNum++) {
			pOL->GetObj(nObjNum)->getMergedHierarchyLayerSet(rSet);
		}
	}
}

void SdrObject::NbcSetLayer(SdrLayerID nLayer)
{
	if(GetLayer() != nLayer)
	{
		mnLayerID = nLayer;
	}
}

void SdrObject::SetLayer(SdrLayerID nLayer)
{
	NbcSetLayer(nLayer);
	SetChanged();
	BroadcastObjectChange();
}

void SdrObject::AddListener(SfxListener& rListener)
{
	ImpForcePlusData();
	if (pPlusData->pBroadcast==NULL) pPlusData->pBroadcast=new SfxBroadcaster;
	rListener.StartListening(*pPlusData->pBroadcast);
}

void SdrObject::RemoveListener(SfxListener& rListener)
{
	if (pPlusData!=NULL && pPlusData->pBroadcast!=NULL) {
		rListener.EndListening(*pPlusData->pBroadcast);
		if (!pPlusData->pBroadcast->HasListeners()) {
			delete pPlusData->pBroadcast;
			pPlusData->pBroadcast=NULL;
		}
	}
}

void SdrObject::AddReference(SdrVirtObj& rVrtObj)
{
	AddListener(rVrtObj);
}

void SdrObject::DelReference(SdrVirtObj& rVrtObj)
{
	RemoveListener(rVrtObj);
}

AutoTimer* SdrObject::ForceAutoTimer()
{
	ImpForcePlusData();
	if (pPlusData->pAutoTimer==NULL) pPlusData->pAutoTimer=new AutoTimer;
	return pPlusData->pAutoTimer;
}

FASTBOOL SdrObject::HasRefPoint() const
{
	return sal_False;
}

Point SdrObject::GetRefPoint() const
{
	return GetCurrentBoundRect().Center();
}

void SdrObject::SetRefPoint(const Point& /*rPnt*/)
{
}

SdrObjList* SdrObject::GetSubList() const
{
	return NULL;
}

SdrObject* SdrObject::GetUpGroup() const
{
	return pObjList!=NULL ? pObjList->GetOwnerObj() : NULL;
}

void SdrObject::SetName(const String& rStr)
{
	if(rStr.Len() && !pPlusData)
	{
		ImpForcePlusData();
	}

	if(pPlusData && pPlusData->aObjName != rStr)
	{
        // --> OD 2009-07-09 #i73249#
        // Undo/Redo for setting object's name
        bool bUndo( false );
        if ( GetModel() && GetModel()->IsUndoEnabled() )
        {
            bUndo = true;
            SdrUndoAction* pUndoAction =
                    GetModel()->GetSdrUndoFactory().CreateUndoObjectStrAttr(
                                                    *this,
                                                    SdrUndoObjStrAttr::OBJ_NAME,
                                                    GetName(),
                                                    rStr );
            GetModel()->BegUndo( pUndoAction->GetComment() );
            GetModel()->AddUndo( pUndoAction );
        }
        // <--
        pPlusData->aObjName = rStr;
        // --> OD 2009-07-09 #i73249#
        if ( bUndo )
        {
            GetModel()->EndUndo();
        }
        // <--
		SetChanged();
        BroadcastObjectChange();
	}
}

String SdrObject::GetName() const
{
	if(pPlusData)
	{
		return pPlusData->aObjName;
	}

	return String();
}

void SdrObject::SetTitle(const String& rStr)
{
	if(rStr.Len() && !pPlusData)
	{
		ImpForcePlusData();
	}

	if(pPlusData && pPlusData->aObjTitle != rStr)
	{
        // --> OD 2009-07-13 #i73249#
        // Undo/Redo for setting object's title
        bool bUndo( false );
        if ( GetModel() && GetModel()->IsUndoEnabled() )
        {
            bUndo = true;
            SdrUndoAction* pUndoAction =
                    GetModel()->GetSdrUndoFactory().CreateUndoObjectStrAttr(
                                                    *this,
                                                    SdrUndoObjStrAttr::OBJ_TITLE,
                                                    GetTitle(),
                                                    rStr );
            GetModel()->BegUndo( pUndoAction->GetComment() );
            GetModel()->AddUndo( pUndoAction );
        }
        // <--
		pPlusData->aObjTitle = rStr;
        // --> OD 2009-07-13 #i73249#
        if ( bUndo )
        {
            GetModel()->EndUndo();
        }
        // <--
		SetChanged();
        BroadcastObjectChange();
	}
}

String SdrObject::GetTitle() const
{
	if(pPlusData)
	{
		return pPlusData->aObjTitle;
	}

	return String();
}

void SdrObject::SetDescription(const String& rStr)
{
	if(rStr.Len() && !pPlusData)
	{
		ImpForcePlusData();
	}

	if(pPlusData && pPlusData->aObjDescription != rStr)
	{
        // --> OD 2009-07-13 #i73249#
        // Undo/Redo for setting object's description
        bool bUndo( false );
        if ( GetModel() && GetModel()->IsUndoEnabled() )
        {
            bUndo = true;
            SdrUndoAction* pUndoAction =
                    GetModel()->GetSdrUndoFactory().CreateUndoObjectStrAttr(
                                                    *this,
                                                    SdrUndoObjStrAttr::OBJ_DESCRIPTION,
                                                    GetDescription(),
                                                    rStr );
            GetModel()->BegUndo( pUndoAction->GetComment() );
            GetModel()->AddUndo( pUndoAction );
        }
        // <--
		pPlusData->aObjDescription = rStr;
        // --> OD 2009-07-13 #i73249#
        if ( bUndo )
        {
            GetModel()->EndUndo();
        }
        // <--
		SetChanged();
        BroadcastObjectChange();
	}
}

String SdrObject::GetDescription() const
{
	if(pPlusData)
	{
		return pPlusData->aObjDescription;
	}

	return String();
}

void SdrObject::SetHTMLName(const String& rStr)
{
	if(rStr.Len() && !pPlusData)
	{
		ImpForcePlusData();
	}

	if(pPlusData && pPlusData->aObjName != rStr)
	{
		pPlusData->aHTMLName = rStr;
		SetChanged();
	}
}

String SdrObject::GetHTMLName() const
{
	if(pPlusData)
	{
		return pPlusData->aHTMLName;
	}

	return String();
}

sal_uInt32 SdrObject::GetOrdNum() const
{
	if (pObjList!=NULL) {
		if (pObjList->IsObjOrdNumsDirty()) {
			pObjList->RecalcObjOrdNums();
		}
	} else ((SdrObject*)this)->nOrdNum=0;
	return nOrdNum;
}




sal_uInt32 SdrObject::GetNavigationPosition (void)
{
    if (pObjList!=NULL && pObjList->RecalcNavigationPositions())
    {
        return mnNavigationPosition;
    }
    else
        return GetOrdNum();
}




void SdrObject::SetNavigationPosition (const sal_uInt32 nNewPosition)
{
    mnNavigationPosition = nNewPosition;
}




// #111111#
// To make clearer that this method may trigger RecalcBoundRect and thus may be
// expensive and sometimes problematic (inside a bigger object change You will get
// non-useful BoundRects sometimes) i rename that method from GetBoundRect() to
// GetCurrentBoundRect().
const Rectangle& SdrObject::GetCurrentBoundRect() const
{
	if(aOutRect.IsEmpty())
	{
		const_cast< SdrObject* >(this)->RecalcBoundRect();
	}

	return aOutRect;
}

// #111111#
// To have a possibility to get the last calculated BoundRect e.g for producing
// the first rectangle for repaints (old and new need to be used) without forcing
// a RecalcBoundRect (which may be problematical and expensive sometimes) i add here
// a new method for accessing the last BoundRect.
const Rectangle& SdrObject::GetLastBoundRect() const
{
	return aOutRect;
}

void SdrObject::RecalcBoundRect()
{
	// #i101680# suppress BoundRect calculations on import(s)
	if(pModel && pModel->isLocked())
		return;

	// central new method which will calculate the BoundRect using primitive geometry
	if(aOutRect.IsEmpty())
	{
    	const drawinglayer::primitive2d::Primitive2DSequence xPrimitives(GetViewContact().getViewIndependentPrimitive2DSequence());

	    if(xPrimitives.hasElements())
	    {
		    // use neutral ViewInformation and get the range of the primitives
		    const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
    		const basegfx::B2DRange aRange(drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xPrimitives, aViewInformation2D));

		    if(!aRange.isEmpty())
		    {
			    aOutRect = Rectangle(
					    (sal_Int32)floor(aRange.getMinX()), (sal_Int32)floor(aRange.getMinY()),
					    (sal_Int32)ceil(aRange.getMaxX()), (sal_Int32)ceil(aRange.getMaxY()));
                return;
		    }
        }
	}
}

void SdrObject::BroadcastObjectChange() const
{
	if( pModel && pModel->isLocked() )
		return;

	sal_Bool bPlusDataBroadcast(pPlusData && pPlusData->pBroadcast);
	sal_Bool bObjectChange(IsInserted() && pModel);

	if(bPlusDataBroadcast || bObjectChange)
	{
		SdrHint aHint(*this);

		if(bPlusDataBroadcast)
		{
			pPlusData->pBroadcast->Broadcast(aHint);
		}

		if(bObjectChange)
		{
			pModel->Broadcast(aHint);
		}
	}
}

void SdrObject::SetChanged()
{
	// #110094#-11
	// For test purposes, use the new ViewContact for change
	// notification now.
	ActionChanged();

	if(IsInserted() && pModel)
	{
		pModel->SetChanged();
	}
}

// Tooling for painting a single object to a OutputDevice.
sal_Bool SdrObject::SingleObjectPainter(OutputDevice& rOut) const
{
	sdr::contact::SdrObjectVector aObjectVector;
	aObjectVector.push_back(const_cast< SdrObject* >(this));

	sdr::contact::ObjectContactOfObjListPainter aPainter(rOut, aObjectVector, GetPage());
	sdr::contact::DisplayInfo aDisplayInfo;

	// do processing
	aPainter.ProcessDisplay(aDisplayInfo);

	return sal_True;
}

sal_Bool SdrObject::LineGeometryUsageIsNecessary() const
{
	XLineStyle eXLS = (XLineStyle)((const XLineStyleItem&)GetMergedItem(XATTR_LINESTYLE)).GetValue();
	return (eXLS != XLINE_NONE);
}

SdrObject* SdrObject::Clone() const
{
	SdrObject* pObj=SdrObjFactory::MakeNewObject(GetObjInventor(),GetObjIdentifier(),NULL);
	if (pObj!=NULL) {
		pObj->pModel=pModel;
		pObj->pPage=pPage;
		*pObj=*this;
	}
	return pObj;
}

void SdrObject::operator=(const SdrObject& rObj)
{
	if(mpProperties)
	{
		delete mpProperties;
		mpProperties = 0L;
	}

	// #110094#
	if(mpViewContact)
	{
		delete mpViewContact;
		mpViewContact = 0L;
	}

	// The Clone() method uses the local copy constructor from the individual
	// sdr::properties::BaseProperties class. Since the target class maybe for another
	// draw object a SdrObject needs to be provided, as in the nromal constructor.
	mpProperties = &rObj.GetProperties().Clone(*this);

	pModel  =rObj.pModel;
	aOutRect=rObj.aOutRect;
	mnLayerID = rObj.mnLayerID;
	aAnchor =rObj.aAnchor;
	bVirtObj=rObj.bVirtObj;
	bSizProt=rObj.bSizProt;
	bMovProt=rObj.bMovProt;
	bNoPrint=rObj.bNoPrint;
	mbVisible=rObj.mbVisible;
	bMarkProt=rObj.bMarkProt;
	//EmptyPresObj wird nicht kopiert: nun doch! (25-07-1995, Joe)
	bEmptyPresObj =rObj.bEmptyPresObj;
	//NotVisibleAsMaster wird nicht kopiert: nun doch! (25-07-1995, Joe)
	bNotVisibleAsMaster=rObj.bNotVisibleAsMaster;
	bSnapRectDirty=sal_True; //rObj.bSnapRectDirty;
	bNotMasterCachable=rObj.bNotMasterCachable;
	if (pPlusData!=NULL) { delete pPlusData; pPlusData=NULL; }
	if (rObj.pPlusData!=NULL) {
		pPlusData=rObj.pPlusData->Clone(this);
	}
	if (pPlusData!=NULL && pPlusData->pBroadcast!=NULL) {
		delete pPlusData->pBroadcast; // der Broadcaster wird nicht mitkopiert
		pPlusData->pBroadcast=NULL;
	}
}

void SdrObject::TakeObjNameSingul(XubString& rName) const
{
	rName=ImpGetResStr(STR_ObjNameSingulNONE);

	String aName( GetName() );
	if(aName.Len())
	{
		rName += sal_Unicode(' ');
		rName += sal_Unicode('\'');
		rName += aName;
		rName += sal_Unicode('\'');
	}
}

void SdrObject::TakeObjNamePlural(XubString& rName) const
{
	rName=ImpGetResStr(STR_ObjNamePluralNONE);
}

void SdrObject::ImpTakeDescriptionStr(sal_uInt16 nStrCacheID, XubString& rStr, sal_uInt16 nVal) const
{
	rStr = ImpGetResStr(nStrCacheID);

	sal_Char aSearchText1[] = "%1";
	sal_Char aSearchText2[] = "%2";
	xub_StrLen nPos = rStr.SearchAscii(aSearchText1);

	if(nPos != STRING_NOTFOUND)
	{
		rStr.Erase(nPos, 2);

		XubString aObjName;

		TakeObjNameSingul(aObjName);
		rStr.Insert(aObjName, nPos);
	}

	nPos = rStr.SearchAscii(aSearchText2);

	if(nPos != STRING_NOTFOUND)
	{
		rStr.Erase(nPos, 2);
		rStr.Insert(UniString::CreateFromInt32(nVal), nPos);
	}
}

XubString SdrObject::GetWinkStr(long nWink, FASTBOOL bNoDegChar) const
{
	XubString aStr;
	if (pModel!=NULL) {
		pModel->TakeWinkStr(nWink,aStr,bNoDegChar);
	}
	return aStr;
}

XubString SdrObject::GetMetrStr(long nVal, MapUnit /*eWantMap*/, FASTBOOL bNoUnitChars) const
{
	XubString aStr;
	if (pModel!=NULL) {
		pModel->TakeMetricStr(nVal,aStr,bNoUnitChars);
	}
	return aStr;
}

basegfx::B2DPolyPolygon SdrObject::TakeXorPoly() const
{
	basegfx::B2DPolyPolygon aRetval;
	const Rectangle aR(GetCurrentBoundRect());
	const basegfx::B2DRange aRange(aR.Left(), aR.Top(), aR.Right(), aR.Bottom());
	aRetval.append(basegfx::tools::createPolygonFromRect(aRange));

	return aRetval;
}

basegfx::B2DPolyPolygon SdrObject::TakeContour() const
{
	basegfx::B2DPolyPolygon aRetval;

    // create cloned object without text, but with XLINE_SOLID,
    // COL_BLACK as line color and XFILL_NONE
	SdrObject* pClone = Clone();

    if(pClone)
    {
        const SdrTextObj* pTextObj = dynamic_cast< const SdrTextObj* >(this);

        if(pTextObj)
	    {
            // no text and no text animation
		    pClone->SetMergedItem(SdrTextAniKindItem(SDRTEXTANI_NONE));
            pClone->SetOutlinerParaObject(0);
	    }

        const SdrEdgeObj* pEdgeObj = dynamic_cast< const SdrEdgeObj* >(this);

        if(pEdgeObj)
	    {
            // create connections if connector, will be cleaned up when
            // deleting the connector again
		    SdrObject* pLeft = pEdgeObj->GetConnectedNode(sal_True);
		    SdrObject* pRight = pEdgeObj->GetConnectedNode(sal_False);

		    if(pLeft)
		    {
			    pClone->ConnectToNode(sal_True, pLeft);
		    }

		    if(pRight)
		    {
			    pClone->ConnectToNode(sal_False, pRight);
		    }
	    }

	    SfxItemSet aNewSet(*GetObjectItemPool());

        // #i101980# ignore LineWidth; that's what the old implementation
        // did. With linewidth, the result may be huge due to fat/thick
        // line decompositions
    	aNewSet.Put(XLineWidthItem(0));

        // solid black lines and no fill
        aNewSet.Put(XLineStyleItem(XLINE_SOLID));
	    aNewSet.Put(XLineColorItem(String(), Color(COL_BLACK)));
	    aNewSet.Put(XFillStyleItem(XFILL_NONE));
	    pClone->SetMergedItemSet(aNewSet);

        // get sequence from clone
	    const sdr::contact::ViewContact& rVC(pClone->GetViewContact());
	    const drawinglayer::primitive2d::Primitive2DSequence xSequence(rVC.getViewIndependentPrimitive2DSequence());

	    if(xSequence.hasElements())
	    {
		    // use neutral ViewInformation
		    const drawinglayer::geometry::ViewInformation2D aViewInformation2D;

		    // create extractor, process and get result (with hairlines as opened polygons)
		    drawinglayer::processor2d::ContourExtractor2D aExtractor(aViewInformation2D, false);
		    aExtractor.process(xSequence);
            const basegfx::B2DPolyPolygonVector& rResult(aExtractor.getExtractedContour());
            const sal_uInt32 nSize(rResult.size());

            // when count is one, it is implied that the object has only it's normal
            // contour anyways and TakeCountour() is to return an empty PolyPolygon
            // (see old implementation for historical reasons)
            if(nSize > 1)
            {
                // the topology for contour is correctly a vector of PolyPolygons; for
                // historical reasons cut it back to a single PolyPolygon here
                for(sal_uInt32 a(0); a < nSize; a++)
                {
                    aRetval.append(rResult[a]);
                }
            }
        }

    	delete pClone;
    }

	return aRetval;
}

sal_uInt32 SdrObject::GetHdlCount() const
{
	return 8L;
}

SdrHdl* SdrObject::GetHdl(sal_uInt32 nHdlNum) const
{
	SdrHdl* pH=NULL;
	const Rectangle& rR=GetSnapRect();
	switch (nHdlNum) {
		case 0: pH=new SdrHdl(rR.TopLeft(),     HDL_UPLFT); break; // Oben links
		case 1: pH=new SdrHdl(rR.TopCenter(),   HDL_UPPER); break; // Oben
		case 2: pH=new SdrHdl(rR.TopRight(),    HDL_UPRGT); break; // Oben rechts
		case 3: pH=new SdrHdl(rR.LeftCenter(),  HDL_LEFT ); break; // Links
		case 4: pH=new SdrHdl(rR.RightCenter(), HDL_RIGHT); break; // Rechts
		case 5: pH=new SdrHdl(rR.BottomLeft(),  HDL_LWLFT); break; // Unten links
		case 6: pH=new SdrHdl(rR.BottomCenter(),HDL_LOWER); break; // Unten
		case 7: pH=new SdrHdl(rR.BottomRight(), HDL_LWRGT); break; // Unten rechts
	}
	return pH;
}

sal_uInt32 SdrObject::GetPlusHdlCount(const SdrHdl& /*rHdl*/) const
{
	return 0L;
}

SdrHdl* SdrObject::GetPlusHdl(const SdrHdl& /*rHdl*/, sal_uInt32 /*nPlNum*/) const
{
	return 0L;
}

void SdrObject::AddToHdlList(SdrHdlList& rHdlList) const
{
	sal_uInt32 nAnz=GetHdlCount();
	for (sal_uInt32 i=0L; i<nAnz; i++) {
		SdrHdl* pHdl=GetHdl(i);
		if (pHdl!=NULL) {
			rHdlList.AddHdl(pHdl);
		}
	}
}

Rectangle SdrObject::ImpDragCalcRect(const SdrDragStat& rDrag) const
{
	Rectangle aTmpRect(GetSnapRect());
	Rectangle aRect(aTmpRect);
	const SdrHdl* pHdl=rDrag.GetHdl();
	SdrHdlKind eHdl=pHdl==NULL ? HDL_MOVE : pHdl->GetKind();
	FASTBOOL bEcke=(eHdl==HDL_UPLFT || eHdl==HDL_UPRGT || eHdl==HDL_LWLFT || eHdl==HDL_LWRGT);
	FASTBOOL bOrtho=rDrag.GetView()!=NULL && rDrag.GetView()->IsOrtho();
	FASTBOOL bBigOrtho=bEcke && bOrtho && rDrag.GetView()->IsBigOrtho();
	Point aPos(rDrag.GetNow());
	FASTBOOL bLft=(eHdl==HDL_UPLFT || eHdl==HDL_LEFT  || eHdl==HDL_LWLFT);
	FASTBOOL bRgt=(eHdl==HDL_UPRGT || eHdl==HDL_RIGHT || eHdl==HDL_LWRGT);
	FASTBOOL bTop=(eHdl==HDL_UPRGT || eHdl==HDL_UPPER || eHdl==HDL_UPLFT);
	FASTBOOL bBtm=(eHdl==HDL_LWRGT || eHdl==HDL_LOWER || eHdl==HDL_LWLFT);
	if (bLft) aTmpRect.Left()  =aPos.X();
	if (bRgt) aTmpRect.Right() =aPos.X();
	if (bTop) aTmpRect.Top()   =aPos.Y();
	if (bBtm) aTmpRect.Bottom()=aPos.Y();
	if (bOrtho) { // Ortho
		long nWdt0=aRect.Right() -aRect.Left();
		long nHgt0=aRect.Bottom()-aRect.Top();
		long nXMul=aTmpRect.Right() -aTmpRect.Left();
		long nYMul=aTmpRect.Bottom()-aTmpRect.Top();
		long nXDiv=nWdt0;
		long nYDiv=nHgt0;
		FASTBOOL bXNeg=(nXMul<0)!=(nXDiv<0);
		FASTBOOL bYNeg=(nYMul<0)!=(nYDiv<0);
		nXMul=Abs(nXMul);
		nYMul=Abs(nYMul);
		nXDiv=Abs(nXDiv);
		nYDiv=Abs(nYDiv);
		Fraction aXFact(nXMul,nXDiv); // Fractions zum kuerzen
		Fraction aYFact(nYMul,nYDiv); // und zum vergleichen
		nXMul=aXFact.GetNumerator();
		nYMul=aYFact.GetNumerator();
		nXDiv=aXFact.GetDenominator();
		nYDiv=aYFact.GetDenominator();
		if (bEcke) { // Eckpunkthandles
			FASTBOOL bUseX=(aXFact<aYFact) != bBigOrtho;
			if (bUseX) {
				long nNeed=long(BigInt(nHgt0)*BigInt(nXMul)/BigInt(nXDiv));
				if (bYNeg) nNeed=-nNeed;
				if (bTop) aTmpRect.Top()=aTmpRect.Bottom()-nNeed;
				if (bBtm) aTmpRect.Bottom()=aTmpRect.Top()+nNeed;
			} else {
				long nNeed=long(BigInt(nWdt0)*BigInt(nYMul)/BigInt(nYDiv));
				if (bXNeg) nNeed=-nNeed;
				if (bLft) aTmpRect.Left()=aTmpRect.Right()-nNeed;
				if (bRgt) aTmpRect.Right()=aTmpRect.Left()+nNeed;
			}
		} else { // Scheitelpunkthandles
			if ((bLft || bRgt) && nXDiv!=0) {
				long nHgt0b=aRect.Bottom()-aRect.Top();
				long nNeed=long(BigInt(nHgt0b)*BigInt(nXMul)/BigInt(nXDiv));
				aTmpRect.Top()-=(nNeed-nHgt0b)/2;
				aTmpRect.Bottom()=aTmpRect.Top()+nNeed;
			}
			if ((bTop || bBtm) && nYDiv!=0) {
				long nWdt0b=aRect.Right()-aRect.Left();
				long nNeed=long(BigInt(nWdt0b)*BigInt(nYMul)/BigInt(nYDiv));
				aTmpRect.Left()-=(nNeed-nWdt0b)/2;
				aTmpRect.Right()=aTmpRect.Left()+nNeed;
			}
		}
	}
	aTmpRect.Justify();
	return aTmpRect;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool SdrObject::hasSpecialDrag() const
{
	return false;
}

bool SdrObject::supportsFullDrag() const
{
    return true;
}

SdrObject* SdrObject::getFullDragClone() const
{
	// default uses simple clone
	return Clone();
}

bool SdrObject::beginSpecialDrag(SdrDragStat& rDrag) const
{
    const SdrHdl* pHdl = rDrag.GetHdl();

    SdrHdlKind eHdl = (pHdl == NULL) ? HDL_MOVE : pHdl->GetKind();

    if(eHdl==HDL_UPLFT || eHdl==HDL_UPPER || eHdl==HDL_UPRGT ||
	    eHdl==HDL_LEFT || eHdl==HDL_RIGHT || eHdl==HDL_LWLFT ||
        eHdl==HDL_LOWER || eHdl==HDL_LWRGT)
    {
        return true;
    }

    return false;
}

bool SdrObject::applySpecialDrag(SdrDragStat& rDrag)
{
	Rectangle aNewRect(ImpDragCalcRect(rDrag));

    if(aNewRect != GetSnapRect())
    {
   		NbcSetSnapRect(aNewRect);
	}

    return true;
}

String SdrObject::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const
{
	return String();
}

basegfx::B2DPolyPolygon SdrObject::getSpecialDragPoly(const SdrDragStat& /*rDrag*/) const
{
    // default has nothing to add
    return basegfx::B2DPolyPolygon();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Create
FASTBOOL SdrObject::BegCreate(SdrDragStat& rStat)
{
	rStat.SetOrtho4Possible();
	Rectangle aRect1(rStat.GetStart(), rStat.GetNow());
	aRect1.Justify();
	rStat.SetActionRect(aRect1);
	aOutRect = aRect1;
	return sal_True;
}

FASTBOOL SdrObject::MovCreate(SdrDragStat& rStat)
{
	rStat.TakeCreateRect(aOutRect);
	rStat.SetActionRect(aOutRect);
	aOutRect.Justify();

	// #i101648# for naked (non-derived) SdrObjects, do not invalidate aOutRect
	// by calling SetBoundRectDirty(); aOutRect IS the geometry for such objects.
	// No derivation implementation calls the parent implementation, so this will
	// cause no further prolems
	//
	// SetBoundRectDirty();
	// bSnapRectDirty=sal_True;

	return sal_True;
}

FASTBOOL SdrObject::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
{
	rStat.TakeCreateRect(aOutRect);
	aOutRect.Justify();

	// #i101648# see description at MovCreate
	//
	// SetRectsDirty();

	return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2);
}

void SdrObject::BrkCreate(SdrDragStat& /*rStat*/)
{
}

FASTBOOL SdrObject::BckCreate(SdrDragStat& /*rStat*/)
{
	return sal_False;
}

basegfx::B2DPolyPolygon SdrObject::TakeCreatePoly(const SdrDragStat& rDrag) const
{
	Rectangle aRect1;
	rDrag.TakeCreateRect(aRect1);
	aRect1.Justify();

	basegfx::B2DPolyPolygon aRetval;
	const basegfx::B2DRange aRange(aRect1.Left(), aRect1.Top(), aRect1.Right(), aRect1.Bottom());
	aRetval.append(basegfx::tools::createPolygonFromRect(aRange));
	return aRetval;
}

Pointer SdrObject::GetCreatePointer() const
{
	return Pointer(POINTER_CROSS);
}

// Transformationen
void SdrObject::NbcMove(const Size& rSiz)
{
	MoveRect(aOutRect,rSiz);
	SetRectsDirty();
}

void SdrObject::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
{
	FASTBOOL bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0);
	FASTBOOL bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0);
	if (bXMirr || bYMirr) {
		Point aRef1(GetSnapRect().Center());
		if (bXMirr) {
			Point aRef2(aRef1);
			aRef2.Y()++;
			NbcMirrorGluePoints(aRef1,aRef2);
		}
		if (bYMirr) {
			Point aRef2(aRef1);
			aRef2.X()++;
			NbcMirrorGluePoints(aRef1,aRef2);
		}
	}
	ResizeRect(aOutRect,rRef,xFact,yFact);
	SetRectsDirty();
}

void SdrObject::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
{
	SetGlueReallyAbsolute(sal_True);
	aOutRect.Move(-rRef.X(),-rRef.Y());
	Rectangle R(aOutRect);
    if (sn==1.0 && cs==0.0) { // 90deg
		aOutRect.Left()  =-R.Bottom();
		aOutRect.Right() =-R.Top();
		aOutRect.Top()   =R.Left();
		aOutRect.Bottom()=R.Right();
    } else if (sn==0.0 && cs==-1.0) { // 180deg
		aOutRect.Left()  =-R.Right();
		aOutRect.Right() =-R.Left();
		aOutRect.Top()   =-R.Bottom();
		aOutRect.Bottom()=-R.Top();
    } else if (sn==-1.0 && cs==0.0) { // 270deg
		aOutRect.Left()  =R.Top();
		aOutRect.Right() =R.Bottom();
		aOutRect.Top()   =-R.Right();
		aOutRect.Bottom()=-R.Left();
	}
	aOutRect.Move(rRef.X(),rRef.Y());
	aOutRect.Justify(); // Sicherheitshalber
	SetRectsDirty();
	NbcRotateGluePoints(rRef,nWink,sn,cs);
	SetGlueReallyAbsolute(sal_False);
}

void SdrObject::NbcMirror(const Point& rRef1, const Point& rRef2)
{
	SetGlueReallyAbsolute(sal_True);
	aOutRect.Move(-rRef1.X(),-rRef1.Y());
	Rectangle R(aOutRect);
	long dx=rRef2.X()-rRef1.X();
	long dy=rRef2.Y()-rRef1.Y();
	if (dx==0) {          // Vertikale Achse
		aOutRect.Left() =-R.Right();
		aOutRect.Right()=-R.Left();
	} else if (dy==0) {   // Horizontale Achse
		aOutRect.Top()   =-R.Bottom();
		aOutRect.Bottom()=-R.Top();
	} else if (dx==dy) {  /* 45 Grad Achse \ */
		aOutRect.Left()  =R.Top();
		aOutRect.Right() =R.Bottom();
		aOutRect.Top()   =R.Left();
		aOutRect.Bottom()=R.Right();
	} else if (dx==-dy) { // 45 Grad Achse /
		aOutRect.Left()  =-R.Bottom();
		aOutRect.Right() =-R.Top();
		aOutRect.Top()   =-R.Right();
		aOutRect.Bottom()=-R.Left();
	}
	aOutRect.Move(rRef1.X(),rRef1.Y());
	aOutRect.Justify(); // Sicherheitshalber
	SetRectsDirty();
	NbcMirrorGluePoints(rRef1,rRef2);
	SetGlueReallyAbsolute(sal_False);
}

void SdrObject::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
{
	SetGlueReallyAbsolute(sal_True);
	NbcShearGluePoints(rRef,nWink,tn,bVShear);
	SetGlueReallyAbsolute(sal_False);
}

void SdrObject::Move(const Size& rSiz)
{
	if (rSiz.Width()!=0 || rSiz.Height()!=0) {
		Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
		// #110094#-14 SendRepaintBroadcast();
		NbcMove(rSiz);
		SetChanged();
		BroadcastObjectChange();
		SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0);
	}
}

void SdrObject::Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
{
	if (xFact.GetNumerator()!=xFact.GetDenominator() || yFact.GetNumerator()!=yFact.GetDenominator()) {
		Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
		// #110094#-14 SendRepaintBroadcast();
		NbcResize(rRef,xFact,yFact);
		SetChanged();
		BroadcastObjectChange();
		SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
	}
}

void SdrObject::Rotate(const Point& rRef, long nWink, double sn, double cs)
{
	if (nWink!=0) {
		Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
		// #110094#-14 SendRepaintBroadcast();
		NbcRotate(rRef,nWink,sn,cs);
		SetChanged();
		BroadcastObjectChange();
		SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
	}
}

void SdrObject::Mirror(const Point& rRef1, const Point& rRef2)
{
	Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
	// #110094#-14 SendRepaintBroadcast();
	NbcMirror(rRef1,rRef2);
	SetChanged();
	BroadcastObjectChange();
	SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
}

void SdrObject::Shear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
{
	if (nWink!=0) {
		Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
		// #110094#-14 SendRepaintBroadcast();
		NbcShear(rRef,nWink,tn,bVShear);
		SetChanged();
		BroadcastObjectChange();
		SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
	}
}

void SdrObject::NbcSetRelativePos(const Point& rPnt)
{
	Point aRelPos0(GetSnapRect().TopLeft()-aAnchor);
	Size aSiz(rPnt.X()-aRelPos0.X(),rPnt.Y()-aRelPos0.Y());
	NbcMove(aSiz); // Der ruft auch das SetRectsDirty()
}

void SdrObject::SetRelativePos(const Point& rPnt)
{
	if (rPnt!=GetRelativePos()) {
		Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
		// #110094#-14 SendRepaintBroadcast();
		NbcSetRelativePos(rPnt);
		SetChanged();
		BroadcastObjectChange();
		SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0);
	}
}

Point SdrObject::GetRelativePos() const
{
	return GetSnapRect().TopLeft()-aAnchor;
}

void SdrObject::NbcSetAnchorPos(const Point& rPnt)
{
	Size aSiz(rPnt.X()-aAnchor.X(),rPnt.Y()-aAnchor.Y());
	aAnchor=rPnt;
	NbcMove(aSiz); // Der ruft auch das SetRectsDirty()
}

void SdrObject::SetAnchorPos(const Point& rPnt)
{
	if (rPnt!=aAnchor) {
		Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
		// #110094#-14 SendRepaintBroadcast();
		NbcSetAnchorPos(rPnt);
		SetChanged();
		BroadcastObjectChange();
		SendUserCall(SDRUSERCALL_MOVEONLY,aBoundRect0);
	}
}

const Point& SdrObject::GetAnchorPos() const
{
	return aAnchor;
}

void SdrObject::RecalcSnapRect()
{
}

const Rectangle& SdrObject::GetSnapRect() const
{
	return aOutRect;
}

void SdrObject::NbcSetSnapRect(const Rectangle& rRect)
{
	aOutRect=rRect;
}

const Rectangle& SdrObject::GetLogicRect() const
{
	return GetSnapRect();
}

void SdrObject::NbcSetLogicRect(const Rectangle& rRect)
{
	NbcSetSnapRect(rRect);
}

void SdrObject::AdjustToMaxRect( const Rectangle& rMaxRect, bool /* bShrinkOnly = false */ )
{
	SetLogicRect( rMaxRect );
}

void SdrObject::SetSnapRect(const Rectangle& rRect)
{
	Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
	// #110094#-14 SendRepaintBroadcast();
	NbcSetSnapRect(rRect);
	SetChanged();
	BroadcastObjectChange();
	SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
}

void SdrObject::SetLogicRect(const Rectangle& rRect)
{
	Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
	// #110094#-14 SendRepaintBroadcast();
	NbcSetLogicRect(rRect);
	SetChanged();
	BroadcastObjectChange();
	SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
}

long SdrObject::GetRotateAngle() const
{
	return 0;
}

long SdrObject::GetShearAngle(FASTBOOL /*bVertical*/) const
{
	return 0;
}

sal_uInt32 SdrObject::GetSnapPointCount() const
{
	return GetPointCount();
}

Point SdrObject::GetSnapPoint(sal_uInt32 i) const
{
	return GetPoint(i);
}

sal_Bool SdrObject::IsPolyObj() const
{
	return sal_False;
}

sal_uInt32 SdrObject::GetPointCount() const
{
	return 0L;
}

Point SdrObject::GetPoint(sal_uInt32 /*i*/) const
{
	return Point();
}

void SdrObject::SetPoint(const Point& rPnt, sal_uInt32 i)
{
	Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
	// #110094#-14 SendRepaintBroadcast();
	NbcSetPoint(rPnt, i);
	SetChanged();
	BroadcastObjectChange();
	SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
}

void SdrObject::NbcSetPoint(const Point& /*rPnt*/, sal_uInt32 /*i*/)
{
}

FASTBOOL SdrObject::HasTextEdit() const
{
	return sal_False;
}

sal_Bool SdrObject::BegTextEdit(SdrOutliner& /*rOutl*/)
{
	return sal_False;
}

void SdrObject::EndTextEdit(SdrOutliner& /*rOutl*/)
{
}

void SdrObject::SetOutlinerParaObject(OutlinerParaObject* pTextObject)
{
	Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
	// #110094#-14 SendRepaintBroadcast();
	NbcSetOutlinerParaObject(pTextObject);
	SetChanged();
	BroadcastObjectChange();
	if (GetCurrentBoundRect()!=aBoundRect0) {
		SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
	}
}

void SdrObject::NbcSetOutlinerParaObject(OutlinerParaObject* /*pTextObject*/)
{
}

OutlinerParaObject* SdrObject::GetOutlinerParaObject() const
{
	return NULL;
}

void SdrObject::NbcReformatText()
{
}

void SdrObject::ReformatText()
{
	Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
	NbcReformatText();
	SetChanged();
	BroadcastObjectChange();
	if (GetCurrentBoundRect()!=aBoundRect0) {
		SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
	}
}

void SdrObject::BurnInStyleSheetAttributes()
{
	GetProperties().ForceStyleToHardAttributes();
}

#define Imp2ndKennung (0x434F4D43)
SdrObjUserData* SdrObject::ImpGetMacroUserData() const
{
	SdrObjUserData* pData=NULL;
	sal_uInt16 nAnz=GetUserDataCount();
	for (sal_uInt16 nNum=nAnz; nNum>0 && pData==NULL;) {
		nNum--;
		pData=GetUserData(nNum);
		if (!pData->HasMacro(this)) pData=NULL;
	}
	return pData;
}

FASTBOOL SdrObject::HasMacro() const
{
	SdrObjUserData* pData=ImpGetMacroUserData();
	return pData!=NULL ? pData->HasMacro(this) : sal_False;
}

SdrObject* SdrObject::CheckMacroHit(const SdrObjMacroHitRec& rRec) const
{
	SdrObjUserData* pData = ImpGetMacroUserData();

    if(pData)
    {
		return pData->CheckMacroHit(rRec, this);
	}

    if(rRec.pPageView)
    {
	    return SdrObjectPrimitiveHit(*this, rRec.aPos, rRec.nTol, *rRec.pPageView, rRec.pVisiLayer, false);
    }

	return 0;
}

Pointer SdrObject::GetMacroPointer(const SdrObjMacroHitRec& rRec) const
{
	SdrObjUserData* pData=ImpGetMacroUserData();
	if (pData!=NULL) {
		return pData->GetMacroPointer(rRec,this);
	}
	return Pointer(POINTER_REFHAND);
}

void SdrObject::PaintMacro(OutputDevice& rOut, const Rectangle& rDirtyRect, const SdrObjMacroHitRec& rRec) const
{
	SdrObjUserData* pData=ImpGetMacroUserData();

    if(pData)
    {
		pData->PaintMacro(rOut,rDirtyRect,rRec,this);
	}
    else
    {
	    const RasterOp eRop(rOut.GetRasterOp());
	    const basegfx::B2DPolyPolygon aPolyPolygon(TakeXorPoly());
	    const sal_uInt32 nCount(aPolyPolygon.count());

        rOut.SetLineColor(COL_BLACK);
        rOut.SetFillColor();
	    rOut.SetRasterOp(ROP_INVERT);

	    for(sal_uInt32 a(0); a < nCount; a++)
	    {
		    rOut.DrawPolyLine(aPolyPolygon.getB2DPolygon(a));
	    }

        rOut.SetRasterOp(eRop);
	}
}

FASTBOOL SdrObject::DoMacro(const SdrObjMacroHitRec& rRec)
{
	SdrObjUserData* pData=ImpGetMacroUserData();
	if (pData!=NULL) {
		return pData->DoMacro(rRec,this);
	}
	return sal_False;
}

XubString SdrObject::GetMacroPopupComment(const SdrObjMacroHitRec& rRec) const
{
	SdrObjUserData* pData=ImpGetMacroUserData();
	if (pData!=NULL) {
		return pData->GetMacroPopupComment(rRec,this);
	}
	return String();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

SdrObjGeoData* SdrObject::NewGeoData() const
{
	return new SdrObjGeoData;
}

void SdrObject::SaveGeoData(SdrObjGeoData& rGeo) const
{
	rGeo.aBoundRect    =GetCurrentBoundRect();
	rGeo.aAnchor       =aAnchor       ;
	rGeo.bMovProt      =bMovProt      ;
	rGeo.bSizProt      =bSizProt      ;
	rGeo.bNoPrint      =bNoPrint      ;
	rGeo.mbVisible	   =mbVisible     ;
	rGeo.bClosedObj    =bClosedObj    ;
	rGeo.mnLayerID = mnLayerID;

	// Benutzerdefinierte Klebepunkte
	if (pPlusData!=NULL && pPlusData->pGluePoints!=NULL) {
		if (rGeo.pGPL!=NULL) {
			*rGeo.pGPL=*pPlusData->pGluePoints;
		} else {
			rGeo.pGPL=new SdrGluePointList(*pPlusData->pGluePoints);
		}
	} else {
		if (rGeo.pGPL!=NULL) {
			delete rGeo.pGPL;
			rGeo.pGPL=NULL;
		}
	}
}

void SdrObject::RestGeoData(const SdrObjGeoData& rGeo)
{
	SetRectsDirty();
	aOutRect      =rGeo.aBoundRect    ;
	aAnchor       =rGeo.aAnchor       ;
	bMovProt      =rGeo.bMovProt      ;
	bSizProt      =rGeo.bSizProt      ;
	bNoPrint      =rGeo.bNoPrint      ;
	mbVisible     =rGeo.mbVisible     ;
	bClosedObj    =rGeo.bClosedObj    ;
	mnLayerID = rGeo.mnLayerID;

	// Benutzerdefinierte Klebepunkte
	if (rGeo.pGPL!=NULL) {
		ImpForcePlusData();
		if (pPlusData->pGluePoints!=NULL) {
			*pPlusData->pGluePoints=*rGeo.pGPL;
		} else {
			pPlusData->pGluePoints=new SdrGluePointList(*rGeo.pGPL);
		}
	} else {
		if (pPlusData!=NULL && pPlusData->pGluePoints!=NULL) {
			delete pPlusData->pGluePoints;
			pPlusData->pGluePoints=NULL;
		}
	}
}

SdrObjGeoData* SdrObject::GetGeoData() const
{
	SdrObjGeoData* pGeo=NewGeoData();
	SaveGeoData(*pGeo);
	return pGeo;
}

void SdrObject::SetGeoData(const SdrObjGeoData& rGeo)
{
	Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
	RestGeoData(rGeo);
	SetChanged();
	BroadcastObjectChange();
	SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// ItemSet access

const SfxItemSet& SdrObject::GetObjectItemSet() const
{
	return GetProperties().GetObjectItemSet();
}

const SfxItemSet& SdrObject::GetMergedItemSet() const
{
	return GetProperties().GetMergedItemSet();
}

void SdrObject::SetObjectItem(const SfxPoolItem& rItem)
{
	GetProperties().SetObjectItem(rItem);
}

void SdrObject::SetMergedItem(const SfxPoolItem& rItem)
{
	GetProperties().SetMergedItem(rItem);
}

void SdrObject::ClearObjectItem(const sal_uInt16 nWhich)
{
	GetProperties().ClearObjectItem(nWhich);
}

void SdrObject::ClearMergedItem(const sal_uInt16 nWhich)
{
	GetProperties().ClearMergedItem(nWhich);
}

void SdrObject::SetObjectItemSet(const SfxItemSet& rSet)
{
	GetProperties().SetObjectItemSet(rSet);
}

void SdrObject::SetMergedItemSet(const SfxItemSet& rSet, sal_Bool bClearAllItems)
{
	GetProperties().SetMergedItemSet(rSet, bClearAllItems);
}

const SfxPoolItem& SdrObject::GetObjectItem(const sal_uInt16 nWhich) const
{
	return GetObjectItemSet().Get(nWhich);
}

SfxMapUnit SdrObject::GetObjectMapUnit() const
{
    SfxMapUnit aRetval(SFX_MAPUNIT_100TH_MM);
    SdrItemPool* pPool = GetObjectItemPool();

    if(pPool)
    {
        aRetval = pPool->GetMetric(0);
    }
    else
    {
        OSL_ENSURE(pPool, "SdrObjects always need a pool (!)");
    }

    return aRetval;
}

const SfxPoolItem& SdrObject::GetMergedItem(const sal_uInt16 nWhich) const
{
	return GetMergedItemSet().Get(nWhich);
}

void SdrObject::SetMergedItemSetAndBroadcast(const SfxItemSet& rSet, sal_Bool bClearAllItems)
{
	GetProperties().SetMergedItemSetAndBroadcast(rSet, bClearAllItems);
}

void SdrObject::ApplyNotPersistAttr(const SfxItemSet& rAttr)
{
	Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
	NbcApplyNotPersistAttr(rAttr);
	SetChanged();
	BroadcastObjectChange();
	SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
}

void SdrObject::NbcApplyNotPersistAttr(const SfxItemSet& rAttr)
{
	const Rectangle& rSnap=GetSnapRect();
	const Rectangle& rLogic=GetLogicRect();
	Point aRef1(rSnap.Center());
	Point aRef2(aRef1); aRef2.Y()++;
	const SfxPoolItem *pPoolItem=NULL;
	if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1X,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		aRef1.X()=((const SdrTransformRef1XItem*)pPoolItem)->GetValue();
	}
	if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1Y,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		aRef1.Y()=((const SdrTransformRef1YItem*)pPoolItem)->GetValue();
	}
	if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2X,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		aRef2.X()=((const SdrTransformRef2XItem*)pPoolItem)->GetValue();
	}
	if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2Y,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		aRef2.Y()=((const SdrTransformRef2YItem*)pPoolItem)->GetValue();
	}

	Rectangle aNewSnap(rSnap);
	if (rAttr.GetItemState(SDRATTR_MOVEX,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrMoveXItem*)pPoolItem)->GetValue();
		aNewSnap.Move(n,0);
	}
	if (rAttr.GetItemState(SDRATTR_MOVEY,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrMoveYItem*)pPoolItem)->GetValue();
		aNewSnap.Move(0,n);
	}
	if (rAttr.GetItemState(SDRATTR_ONEPOSITIONX,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrOnePositionXItem*)pPoolItem)->GetValue();
		aNewSnap.Move(n-aNewSnap.Left(),0);
	}
	if (rAttr.GetItemState(SDRATTR_ONEPOSITIONY,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrOnePositionYItem*)pPoolItem)->GetValue();
		aNewSnap.Move(0,n-aNewSnap.Top());
	}
	if (rAttr.GetItemState(SDRATTR_ONESIZEWIDTH,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrOneSizeWidthItem*)pPoolItem)->GetValue();
		aNewSnap.Right()=aNewSnap.Left()+n;
	}
	if (rAttr.GetItemState(SDRATTR_ONESIZEHEIGHT,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrOneSizeHeightItem*)pPoolItem)->GetValue();
		aNewSnap.Bottom()=aNewSnap.Top()+n;
	}
	if (aNewSnap!=rSnap) {
		if (aNewSnap.GetSize()==rSnap.GetSize()) {
			NbcMove(Size(aNewSnap.Left()-rSnap.Left(),aNewSnap.Top()-rSnap.Top()));
		} else {
			NbcSetSnapRect(aNewSnap);
		}
	}

	if (rAttr.GetItemState(SDRATTR_SHEARANGLE,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrShearAngleItem*)pPoolItem)->GetValue();
		n-=GetShearAngle();
		if (n!=0) {
			double nTan=tan(n*nPi180);
			NbcShear(aRef1,n,nTan,sal_False);
		}
	}
	if (rAttr.GetItemState(SDRATTR_ROTATEANGLE,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrRotateAngleItem*)pPoolItem)->GetValue();
		n-=GetRotateAngle();
		if (n!=0) {
			double nSin=sin(n*nPi180);
			double nCos=cos(n*nPi180);
			NbcRotate(aRef1,n,nSin,nCos);
		}
	}
	if (rAttr.GetItemState(SDRATTR_ROTATEONE,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrRotateOneItem*)pPoolItem)->GetValue();
		double nSin=sin(n*nPi180);
		double nCos=cos(n*nPi180);
		NbcRotate(aRef1,n,nSin,nCos);
	}
	if (rAttr.GetItemState(SDRATTR_HORZSHEARONE,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrHorzShearOneItem*)pPoolItem)->GetValue();
		double nTan=tan(n*nPi180);
		NbcShear(aRef1,n,nTan,sal_False);
	}
	if (rAttr.GetItemState(SDRATTR_VERTSHEARONE,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrVertShearOneItem*)pPoolItem)->GetValue();
		double nTan=tan(n*nPi180);
		NbcShear(aRef1,n,nTan,sal_True);
	}

	if (rAttr.GetItemState(SDRATTR_OBJMOVEPROTECT,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		bool b=((const SdrObjMoveProtectItem*)pPoolItem)->GetValue();
		SetMoveProtect(b);
	}
	if (rAttr.GetItemState(SDRATTR_OBJSIZEPROTECT,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		bool b=((const SdrObjSizeProtectItem*)pPoolItem)->GetValue();
		SetResizeProtect(b);
	}

	/* #67368# move protect always sets size protect */
	if( IsMoveProtect() )
		SetResizeProtect( true );

	if (rAttr.GetItemState(SDRATTR_OBJPRINTABLE,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		bool b=((const SdrObjPrintableItem*)pPoolItem)->GetValue();
		SetPrintable(b);
	}

	if (rAttr.GetItemState(SDRATTR_OBJVISIBLE,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		bool b=((const SdrObjVisibleItem*)pPoolItem)->GetValue();
		SetVisible(b);
	}

	SdrLayerID nLayer=SDRLAYER_NOTFOUND;
	if (rAttr.GetItemState(SDRATTR_LAYERID,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		nLayer=((const SdrLayerIdItem*)pPoolItem)->GetValue();
	}
	if (rAttr.GetItemState(SDRATTR_LAYERNAME,sal_True,&pPoolItem)==SFX_ITEM_SET && pModel!=NULL) {
		XubString aLayerName=((const SdrLayerNameItem*)pPoolItem)->GetValue();
		const SdrLayerAdmin* pLayAd=pPage!=NULL ? &pPage->GetLayerAdmin() : pModel!=NULL ? &pModel->GetLayerAdmin() : NULL;
		if (pLayAd!=NULL) {
			const SdrLayer* pLayer=pLayAd->GetLayer(aLayerName, sal_True);
			if (pLayer!=NULL) {
				nLayer=pLayer->GetID();
			}
		}

	}
	if (nLayer!=SDRLAYER_NOTFOUND) {
		NbcSetLayer(nLayer);
	}

	if (rAttr.GetItemState(SDRATTR_OBJECTNAME,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		XubString aName=((const SdrObjectNameItem*)pPoolItem)->GetValue();
		SetName(aName);
	}
	Rectangle aNewLogic(rLogic);
	if (rAttr.GetItemState(SDRATTR_LOGICSIZEWIDTH,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrLogicSizeWidthItem*)pPoolItem)->GetValue();
		aNewLogic.Right()=aNewLogic.Left()+n;
	}
	if (rAttr.GetItemState(SDRATTR_LOGICSIZEHEIGHT,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		long n=((const SdrLogicSizeHeightItem*)pPoolItem)->GetValue();
		aNewLogic.Bottom()=aNewLogic.Top()+n;
	}
	if (aNewLogic!=rLogic) {
		NbcSetLogicRect(aNewLogic);
	}
	Fraction aResizeX(1,1);
	Fraction aResizeY(1,1);
	if (rAttr.GetItemState(SDRATTR_RESIZEXONE,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		aResizeX*=((const SdrResizeXOneItem*)pPoolItem)->GetValue();
	}
	if (rAttr.GetItemState(SDRATTR_RESIZEYONE,sal_True,&pPoolItem)==SFX_ITEM_SET) {
		aResizeY*=((const SdrResizeYOneItem*)pPoolItem)->GetValue();
	}
	if (aResizeX!=Fraction(1,1) || aResizeY!=Fraction(1,1)) {
		NbcResize(aRef1,aResizeX,aResizeY);
	}
}

void lcl_SetItem(SfxItemSet& rAttr, FASTBOOL bMerge, const SfxPoolItem& rItem)
{
	if (bMerge) rAttr.MergeValue(rItem,sal_True);
	else rAttr.Put(rItem);
}

void SdrObject::TakeNotPersistAttr(SfxItemSet& rAttr, FASTBOOL bMerge) const
{
	const Rectangle& rSnap=GetSnapRect();
	const Rectangle& rLogic=GetLogicRect();
	lcl_SetItem(rAttr,bMerge,SdrObjMoveProtectItem(IsMoveProtect()));
	lcl_SetItem(rAttr,bMerge,SdrObjSizeProtectItem(IsResizeProtect()));
	lcl_SetItem(rAttr,bMerge,SdrObjPrintableItem(IsPrintable()));
	lcl_SetItem(rAttr,bMerge,SdrObjVisibleItem(IsVisible()));
	lcl_SetItem(rAttr,bMerge,SdrRotateAngleItem(GetRotateAngle()));
	lcl_SetItem(rAttr,bMerge,SdrShearAngleItem(GetShearAngle()));
	lcl_SetItem(rAttr,bMerge,SdrOneSizeWidthItem(rSnap.GetWidth()-1));
	lcl_SetItem(rAttr,bMerge,SdrOneSizeHeightItem(rSnap.GetHeight()-1));
	lcl_SetItem(rAttr,bMerge,SdrOnePositionXItem(rSnap.Left()));
	lcl_SetItem(rAttr,bMerge,SdrOnePositionYItem(rSnap.Top()));
	if (rLogic.GetWidth()!=rSnap.GetWidth()) {
		lcl_SetItem(rAttr,bMerge,SdrLogicSizeWidthItem(rLogic.GetWidth()-1));
	}
	if (rLogic.GetHeight()!=rSnap.GetHeight()) {
		lcl_SetItem(rAttr,bMerge,SdrLogicSizeHeightItem(rLogic.GetHeight()-1));
	}
	XubString aName(GetName());

	if(aName.Len())
	{
		lcl_SetItem(rAttr, bMerge, SdrObjectNameItem(aName));
	}

	lcl_SetItem(rAttr,bMerge,SdrLayerIdItem(GetLayer()));
	const SdrLayerAdmin* pLayAd=pPage!=NULL ? &pPage->GetLayerAdmin() : pModel!=NULL ? &pModel->GetLayerAdmin() : NULL;
	if (pLayAd!=NULL) {
		const SdrLayer* pLayer=pLayAd->GetLayerPerID(GetLayer());
		if (pLayer!=NULL) {
			lcl_SetItem(rAttr,bMerge,SdrLayerNameItem(pLayer->GetName()));
		}
	}
	Point aRef1(rSnap.Center());
	Point aRef2(aRef1); aRef2.Y()++;
	lcl_SetItem(rAttr,bMerge,SdrTransformRef1XItem(aRef1.X()));
	lcl_SetItem(rAttr,bMerge,SdrTransformRef1YItem(aRef1.Y()));
	lcl_SetItem(rAttr,bMerge,SdrTransformRef2XItem(aRef2.X()));
	lcl_SetItem(rAttr,bMerge,SdrTransformRef2YItem(aRef2.Y()));
}

SfxStyleSheet* SdrObject::GetStyleSheet() const
{
	return GetProperties().GetStyleSheet();
}

void SdrObject::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr)
{
	Rectangle aBoundRect0;

	if(pUserCall)
		aBoundRect0 = GetLastBoundRect();

	// #110094#-14 SendRepaintBroadcast();
	NbcSetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr);
	SetChanged();
	BroadcastObjectChange();
	SendUserCall(SDRUSERCALL_CHGATTR, aBoundRect0);
}

void SdrObject::NbcSetStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr)
{
	// only allow graphic and presentation styles for shapes
	if( pNewStyleSheet && (pNewStyleSheet->GetFamily() == SFX_STYLE_FAMILY_PARA) && (pNewStyleSheet->GetFamily() == SFX_STYLE_FAMILY_PAGE) )
		return;

	GetProperties().SetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr);
}

// Das Broadcasting beim Setzen der Attribute wird vom AttrObj gemanagt
////////////////////////////////////////////////////////////////////////////////////////////////////

FASTBOOL SdrObject::IsNode() const
{
	return sal_True;
}

SdrGluePoint SdrObject::GetVertexGluePoint(sal_uInt16 nPosNum) const
{
	// #i41936# Use SnapRect for default GluePoints
	const Rectangle aR(GetSnapRect());
	Point aPt;

	switch(nPosNum)
	{
		case 0 : aPt = aR.TopCenter();    break;
		case 1 : aPt = aR.RightCenter();  break;
		case 2 : aPt = aR.BottomCenter(); break;
		case 3 : aPt = aR.LeftCenter();   break;
	}

	aPt -= aR.Center();
	SdrGluePoint aGP(aPt);
	aGP.SetPercent(sal_False);

	return aGP;
}

SdrGluePoint SdrObject::GetCornerGluePoint(sal_uInt16 nPosNum) const
{
	Rectangle aR(GetCurrentBoundRect());
	Point aPt;
	switch (nPosNum) {
		case 0 : aPt=aR.TopLeft();     break;
		case 1 : aPt=aR.TopRight();    break;
		case 2 : aPt=aR.BottomRight(); break;
		case 3 : aPt=aR.BottomLeft();  break;
	}
	aPt-=GetSnapRect().Center();
	SdrGluePoint aGP(aPt);
	aGP.SetPercent(sal_False);
	return aGP;
}

const SdrGluePointList* SdrObject::GetGluePointList() const
{
	if (pPlusData!=NULL) return pPlusData->pGluePoints;
	return NULL;
}

//SdrGluePointList* SdrObject::GetGluePointList()
//{
//	if (pPlusData!=NULL) return pPlusData->pGluePoints;
//	return NULL;
//}

SdrGluePointList* SdrObject::ForceGluePointList()
{
	ImpForcePlusData();
	if (pPlusData->pGluePoints==NULL) {
		pPlusData->pGluePoints=new SdrGluePointList;
	}
	return pPlusData->pGluePoints;
}

void SdrObject::SetGlueReallyAbsolute(FASTBOOL bOn)
{
	// erst Const-Aufruf um zu sehen, ob
	// ueberhaupt Klebepunkte da sind
	// const-Aufruf erzwingen!
	if (GetGluePointList()!=NULL) {
		SdrGluePointList* pGPL=ForceGluePointList();
		pGPL->SetReallyAbsolute(bOn,*this);
	}
}

void SdrObject::NbcRotateGluePoints(const Point& rRef, long nWink, double sn, double cs)
{
	// erst Const-Aufruf um zu sehen, ob
	// ueberhaupt Klebepunkte da sind
	// const-Aufruf erzwingen!
	if (GetGluePointList()!=NULL) {
		SdrGluePointList* pGPL=ForceGluePointList();
		pGPL->Rotate(rRef,nWink,sn,cs,this);
	}
}

void SdrObject::NbcMirrorGluePoints(const Point& rRef1, const Point& rRef2)
{
	// erst Const-Aufruf um zu sehen, ob
	// ueberhaupt Klebepunkte da sind
	// const-Aufruf erzwingen!
	if (GetGluePointList()!=NULL) {
		SdrGluePointList* pGPL=ForceGluePointList();
		pGPL->Mirror(rRef1,rRef2,this);
	}
}

void SdrObject::NbcShearGluePoints(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
{
	// erst Const-Aufruf um zu sehen, ob
	// ueberhaupt Klebepunkte da sind
	// const-Aufruf erzwingen!
	if (GetGluePointList()!=NULL) {
		SdrGluePointList* pGPL=ForceGluePointList();
		pGPL->Shear(rRef,nWink,tn,bVShear,this);
	}
}

FASTBOOL SdrObject::IsEdge() const
{
	return sal_False;
}

void SdrObject::ConnectToNode(FASTBOOL /*bTail1*/, SdrObject* /*pObj*/)
{
}

void SdrObject::DisconnectFromNode(FASTBOOL /*bTail1*/)
{
}

SdrObject* SdrObject::GetConnectedNode(FASTBOOL /*bTail1*/) const
{
	return NULL;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void extractLineContourFromPrimitive2DSequence(
    const drawinglayer::primitive2d::Primitive2DSequence& rxSequence,
    basegfx::B2DPolygonVector& rExtractedHairlines,
    basegfx::B2DPolyPolygonVector& rExtractedLineFills)
{
    rExtractedHairlines.clear();
    rExtractedLineFills.clear();

    if(rxSequence.hasElements())
    {
        // use neutral ViewInformation
        const drawinglayer::geometry::ViewInformation2D aViewInformation2D;

        // create extractor, process and get result
        drawinglayer::processor2d::LineGeometryExtractor2D aExtractor(aViewInformation2D);
        aExtractor.process(rxSequence);

        // copy line results
        rExtractedHairlines = aExtractor.getExtractedHairlines();

        // copy fill rsults
        rExtractedLineFills = aExtractor.getExtractedLineFills();
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

SdrObject* SdrObject::ImpConvertToContourObj(SdrObject* pRet, sal_Bool bForceLineDash) const
{
	bool bNoChange(true);

	if(pRet->LineGeometryUsageIsNecessary())
	{
		basegfx::B2DPolyPolygon aMergedLineFillPolyPolygon;
		basegfx::B2DPolyPolygon aMergedHairlinePolyPolygon;
		const drawinglayer::primitive2d::Primitive2DSequence xSequence(pRet->GetViewContact().getViewIndependentPrimitive2DSequence());

		if(xSequence.hasElements())
		{
            basegfx::B2DPolygonVector aExtractedHairlines;
            basegfx::B2DPolyPolygonVector aExtractedLineFills;

            extractLineContourFromPrimitive2DSequence(xSequence, aExtractedHairlines, aExtractedLineFills);

			if(!aExtractedHairlines.empty())
			{
				// for SdrObject creation, just copy all to a single Hairline-PolyPolygon
				for(sal_uInt32 a(0); a < aExtractedHairlines.size(); a++)
				{
					aMergedHairlinePolyPolygon.append(aExtractedHairlines[a]);
				}
			}

			// check for fill rsults
			if(!aExtractedLineFills.empty())
			{
				// merge to a single PolyPolygon (OR)
				aMergedLineFillPolyPolygon = basegfx::tools::mergeToSinglePolyPolygon(aExtractedLineFills);
			}
		}

		if(aMergedLineFillPolyPolygon.count() || (bForceLineDash && aMergedHairlinePolyPolygon.count()))
		{
			SfxItemSet aSet(pRet->GetMergedItemSet());
			XFillStyle eOldFillStyle = ((const XFillStyleItem&)(aSet.Get(XATTR_FILLSTYLE))).GetValue();
			SdrPathObj* aLinePolygonPart = NULL;
			SdrPathObj* aLineHairlinePart = NULL;
			bool bBuildGroup(false);

			if(aMergedLineFillPolyPolygon.count())
			{
                // create SdrObject for filled line geometry
				aLinePolygonPart = new SdrPathObj(OBJ_PATHFILL, aMergedLineFillPolyPolygon);
				aLinePolygonPart->SetModel(pRet->GetModel());

                // correct item properties
				aSet.Put(XLineWidthItem(0L));
				aSet.Put(XLineStyleItem(XLINE_NONE));
				Color aColorLine = ((const XLineColorItem&)(aSet.Get(XATTR_LINECOLOR))).GetColorValue();
				sal_uInt16 nTransLine = ((const XLineTransparenceItem&)(aSet.Get(XATTR_LINETRANSPARENCE))).GetValue();
				aSet.Put(XFillColorItem(XubString(), aColorLine));
				aSet.Put(XFillStyleItem(XFILL_SOLID));
				aSet.Put(XFillTransparenceItem(nTransLine));

				aLinePolygonPart->SetMergedItemSet(aSet);
			}

			if(aMergedHairlinePolyPolygon.count())
			{
                // create SdrObject for hairline geometry
				// OBJ_PATHLINE is necessary here, not OBJ_PATHFILL. This is intended
				// to get a non-filled object. If the poly is closed, the PathObj takes care for
				// the correct closed state.
				aLineHairlinePart = new SdrPathObj(OBJ_PATHLINE, aMergedHairlinePolyPolygon);
				aLineHairlinePart->SetModel(pRet->GetModel());

				aSet.Put(XLineWidthItem(0L));
				aSet.Put(XFillStyleItem(XFILL_NONE));
				aSet.Put(XLineStyleItem(XLINE_SOLID));

				// it is also necessary to switch off line start and ends here
				aSet.Put(XLineStartWidthItem(0));
				aSet.Put(XLineEndWidthItem(0));

				aLineHairlinePart->SetMergedItemSet(aSet);

				if(aLinePolygonPart)
                {
					bBuildGroup = true;
                }
			}

			// check if original geometry should be added (e.g. filled and closed)
			bool bAddOriginalGeometry(false);
			SdrPathObj* pPath = PTR_CAST(SdrPathObj, pRet);

            if(pPath && pPath->IsClosed())
			{
				if(eOldFillStyle != XFILL_NONE)
				{
					// #107600# use new boolean here
					bAddOriginalGeometry = true;
				}
			}

			// do we need a group?
			if(bBuildGroup || bAddOriginalGeometry)
			{
				SdrObject* pGroup = new SdrObjGroup;
				pGroup->SetModel(pRet->GetModel());

				if(bAddOriginalGeometry)
				{
					// Add a clone of the original geometry.
					aSet.ClearItem();
					aSet.Put(pRet->GetMergedItemSet());
					aSet.Put(XLineStyleItem(XLINE_NONE));
					aSet.Put(XLineWidthItem(0L));

					SdrObject* pClone = pRet->Clone();

					pClone->SetModel(pRet->GetModel());
					pClone->SetMergedItemSet(aSet);

					pGroup->GetSubList()->NbcInsertObject(pClone);
				}

				if(aLinePolygonPart)
				{
					pGroup->GetSubList()->NbcInsertObject(aLinePolygonPart);
				}

				if(aLineHairlinePart)
				{
					pGroup->GetSubList()->NbcInsertObject(aLineHairlinePart);
				}

				pRet = pGroup;

				// be more careful with the state describing bool
				bNoChange = false;
			}
			else
			{
				if(aLinePolygonPart)
				{
					pRet = aLinePolygonPart;
					// be more careful with the state describing bool
					bNoChange = false;
				}
				else if(aLineHairlinePart)
				{
					pRet = aLineHairlinePart;
					// be more careful with the state describing bool
					bNoChange = false;
				}
			}
		}
	}

	if(bNoChange)
	{
        // due to current method usage, create and return a clone when nothing has changed
		SdrObject* pClone = pRet->Clone();
		pClone->SetModel(pRet->GetModel());
		pRet = pClone;
	}

	return pRet;
}

// convert this path object to contour object, even when it is a group
SdrObject* SdrObject::ConvertToContourObj(SdrObject* pRet, sal_Bool bForceLineDash) const
{
	if(pRet->ISA(SdrObjGroup))
	{
		SdrObjList* pObjList2 = pRet->GetSubList();
		SdrObject* pGroup = new SdrObjGroup;
		pGroup->SetModel(pRet->GetModel());

		for(sal_uInt32 a=0;a<pObjList2->GetObjCount();a++)
		{
			SdrObject* pIterObj = pObjList2->GetObj(a);
			pGroup->GetSubList()->NbcInsertObject(ConvertToContourObj(pIterObj, bForceLineDash));
		}

		pRet = pGroup;
	}
	else
	{
        if(pRet && pRet->ISA(SdrPathObj))
        {
            SdrPathObj* pPathObj = (SdrPathObj*)pRet;

            // bezier geometry got created, even for straight edges since the given
            // object is a result of DoConvertToPolyObj. For conversion to contour
            // this is not really needed and can be reduced again AFAP
            pPathObj->SetPathPoly(basegfx::tools::simplifyCurveSegments(pPathObj->GetPathPoly()));
        }

		pRet = ImpConvertToContourObj(pRet, bForceLineDash);
	}

	// #i73441# preserve LayerID
	if(pRet && pRet->GetLayer() != GetLayer())
	{
		pRet->SetLayer(GetLayer());
	}

	return pRet;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

SdrObject* SdrObject::ConvertToPolyObj(sal_Bool bBezier, sal_Bool bLineToArea) const
{
	SdrObject* pRet = DoConvertToPolyObj(bBezier, true);

	if(pRet && bLineToArea)
	{
		SdrObject* pNewRet = ConvertToContourObj(pRet);
		delete pRet;
		pRet = pNewRet;
	}

	// #i73441# preserve LayerID
	if(pRet && pRet->GetLayer() != GetLayer())
	{
		pRet->SetLayer(GetLayer());
	}

	return pRet;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

SdrObject* SdrObject::DoConvertToPolyObj(sal_Bool /*bBezier*/, bool /*bAddText*/) const
{
	return NULL;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SdrObject::SetInserted(sal_Bool bIns)
{
	if (bIns!=IsInserted()) {
		bInserted=bIns;
		Rectangle aBoundRect0(GetLastBoundRect());
		if (bIns) SendUserCall(SDRUSERCALL_INSERTED,aBoundRect0);
		else SendUserCall(SDRUSERCALL_REMOVED,aBoundRect0);

		if (pPlusData!=NULL && pPlusData->pBroadcast!=NULL) { // #42522#
			SdrHint aHint(*this);
			aHint.SetKind(bIns?HINT_OBJINSERTED:HINT_OBJREMOVED);
			pPlusData->pBroadcast->Broadcast(aHint);
		}
	}
}

void SdrObject::SetMoveProtect(sal_Bool bProt)
{
	if(IsMoveProtect() != bProt)
	{
		// #i77187# secured and simplified
		bMovProt = bProt;
		SetChanged();
		BroadcastObjectChange();
	}
}

void SdrObject::SetResizeProtect(sal_Bool bProt)
{
	if(IsResizeProtect() != bProt)
	{
		// #i77187# secured and simplified
		bSizProt = bProt;
		SetChanged();
		BroadcastObjectChange();
	}
}

void SdrObject::SetPrintable(sal_Bool bPrn)
{
	if( bPrn == bNoPrint )
	{
		bNoPrint=!bPrn;
		SetChanged();
		if (IsInserted() && pModel!=NULL)
		{
			SdrHint aHint(*this);
			pModel->Broadcast(aHint);
		}
	}
}

void SdrObject::SetVisible(sal_Bool bVisible)
{
	if( bVisible != mbVisible )
	{
		mbVisible = bVisible;
		SetChanged();
		if (IsInserted() && pModel!=NULL)
		{
			SdrHint aHint(*this);
			pModel->Broadcast(aHint);
		}
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

sal_uInt16 SdrObject::GetUserDataCount() const
{
	if (pPlusData==NULL || pPlusData->pUserDataList==NULL) return 0;
	return pPlusData->pUserDataList->GetUserDataCount();
}

SdrObjUserData* SdrObject::GetUserData(sal_uInt16 nNum) const
{
	if (pPlusData==NULL || pPlusData->pUserDataList==NULL) return NULL;
	return pPlusData->pUserDataList->GetUserData(nNum);
}

void SdrObject::InsertUserData(SdrObjUserData* pData, sal_uInt16 nPos)
{
	if (pData!=NULL) {
		ImpForcePlusData();
		if (pPlusData->pUserDataList==NULL) pPlusData->pUserDataList=new SdrObjUserDataList;
		pPlusData->pUserDataList->InsertUserData(pData,nPos);
	} else {
		DBG_ERROR("SdrObject::InsertUserData(): pData ist NULL-Pointer");
	}
}

void SdrObject::DeleteUserData(sal_uInt16 nNum)
{
	sal_uInt16 nAnz=GetUserDataCount();
	if (nNum<nAnz) {
		pPlusData->pUserDataList->DeleteUserData(nNum);
		if (nAnz==1)  {
			delete pPlusData->pUserDataList;
			pPlusData->pUserDataList=NULL;
		}
	} else {
		DBG_ERROR("SdrObject::DeleteUserData(): ungueltiger Index");
	}
}

void SdrObject::SendUserCall(SdrUserCallType eUserCall, const Rectangle& rBoundRect) const
{
	SdrObjGroup* pGroup = NULL;

	if( pObjList && pObjList->GetListKind() == SDROBJLIST_GROUPOBJ )
		pGroup = (SdrObjGroup*) pObjList->GetOwnerObj();

	if ( pUserCall )
	{
		// UserCall ausfuehren
		pUserCall->Changed( *this, eUserCall, rBoundRect );
	}

	while( pGroup )
	{
		// Gruppe benachrichtigen
		if( pGroup->GetUserCall() )
		{
			SdrUserCallType eChildUserType = SDRUSERCALL_CHILD_CHGATTR;

			switch( eUserCall )
			{
				case SDRUSERCALL_MOVEONLY:
					eChildUserType = SDRUSERCALL_CHILD_MOVEONLY;
				break;

				case SDRUSERCALL_RESIZE:
					eChildUserType = SDRUSERCALL_CHILD_RESIZE;
				break;

				case SDRUSERCALL_CHGATTR:
					eChildUserType = SDRUSERCALL_CHILD_CHGATTR;
				break;

				case SDRUSERCALL_DELETE:
					eChildUserType = SDRUSERCALL_CHILD_DELETE;
				break;

				case SDRUSERCALL_COPY:
					eChildUserType = SDRUSERCALL_CHILD_COPY;
				break;

				case SDRUSERCALL_INSERTED:
					eChildUserType = SDRUSERCALL_CHILD_INSERTED;
				break;

				case SDRUSERCALL_REMOVED:
					eChildUserType = SDRUSERCALL_CHILD_REMOVED;
				break;

				default: break;
			}

			pGroup->GetUserCall()->Changed( *this, eChildUserType, rBoundRect );
		}

		if( pGroup->GetObjList()                                       &&
			pGroup->GetObjList()->GetListKind() == SDROBJLIST_GROUPOBJ &&
			pGroup != (SdrObjGroup*) pObjList->GetOwnerObj() )
			pGroup = (SdrObjGroup*) pObjList->GetOwnerObj();
		else
			pGroup = NULL;
	}

    // notify our UNO shape listeners
    switch ( eUserCall )
    {
    case SDRUSERCALL_RESIZE:
        notifyShapePropertyChange( ::svx::eShapeSize );
        // fall through - RESIZE might also imply a change of the position
    case SDRUSERCALL_MOVEONLY:
        notifyShapePropertyChange( ::svx::eShapePosition );
        break;
    default:
        // not interested in
        break;
    }
}

// ItemPool fuer dieses Objekt wechseln
void SdrObject::MigrateItemPool(SfxItemPool* pSrcPool, SfxItemPool* pDestPool, SdrModel* pNewModel)
{
	if(pSrcPool && pDestPool && (pSrcPool != pDestPool))
	{
		GetProperties().MoveToItemPool(pSrcPool, pDestPool, pNewModel);
	}
}

sal_Bool SdrObject::IsTransparent( sal_Bool /*bCheckForAlphaChannel*/) const
{
	bool bRet = false;

	if( IsGroupObject() )
	{
		SdrObjListIter aIter( *GetSubList(), IM_DEEPNOGROUPS );

		for( SdrObject*	pO = aIter.Next(); pO && !bRet; pO = aIter.Next() )
		{
			const SfxItemSet& rAttr = pO->GetMergedItemSet();

			if( ( ( (const XFillTransparenceItem&) rAttr.Get( XATTR_FILLTRANSPARENCE ) ).GetValue() ||
				  ( (const XLineTransparenceItem&) rAttr.Get( XATTR_LINETRANSPARENCE ) ).GetValue()	) ||
				( ( rAttr.GetItemState( XATTR_FILLFLOATTRANSPARENCE ) == SFX_ITEM_SET ) &&
				  ( (const XFillFloatTransparenceItem&) rAttr.Get( XATTR_FILLFLOATTRANSPARENCE ) ).IsEnabled() ) )
			{
				bRet = sal_True;
			}
			else if( pO->ISA( SdrGrafObj ) )
			{
				SdrGrafObj* pGrafObj = (SdrGrafObj*) pO;
				if( ( (const SdrGrafTransparenceItem&) rAttr.Get( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() ||
                    ( pGrafObj->GetGraphicType() == GRAPHIC_BITMAP && pGrafObj->GetGraphic().GetBitmapEx().IsAlpha() ) )
				{
					bRet = sal_True;
				}
			}
		}
	}
	else
	{
		const SfxItemSet& rAttr = GetMergedItemSet();

		if( ( ( (const XFillTransparenceItem&) rAttr.Get( XATTR_FILLTRANSPARENCE ) ).GetValue() ||
			  ( (const XLineTransparenceItem&) rAttr.Get( XATTR_LINETRANSPARENCE ) ).GetValue()	) ||
			( ( rAttr.GetItemState( XATTR_FILLFLOATTRANSPARENCE ) == SFX_ITEM_SET ) &&
			  ( (const XFillFloatTransparenceItem&) rAttr.Get( XATTR_FILLFLOATTRANSPARENCE ) ).IsEnabled() ) )
		{
			bRet = sal_True;
		}
		else if( ISA( SdrGrafObj ) )
		{
			SdrGrafObj* pGrafObj = (SdrGrafObj*) this;

			// #i25616#
			bRet = pGrafObj->IsObjectTransparent();
		}
	}

	return bRet;
}

void SdrObject::impl_setUnoShape( const uno::Reference< uno::XInterface >& _rxUnoShape )
{
	maWeakUnoShape = _rxUnoShape;
	mpSvxShape = SvxShape::getImplementation( _rxUnoShape );
//    OSL_ENSURE( mpSvxShape || !_rxUnoShape.is(),
//        "SdrObject::setUnoShape: not sure it's a good idea to have an XShape which is not implemented by SvxShape ..." );
}

/** only for internal use! */
SvxShape* SdrObject::getSvxShape()
{
    DBG_TESTSOLARMUTEX();
        // retrieving the impl pointer and subsequently using it is not thread-safe, of course, so it needs to be
        // guarded by the SolarMutex

    uno::Reference< uno::XInterface > xShape( maWeakUnoShape );
#if OSL_DEBUG_LEVE > 0
    OSL_ENSURE( !( !xShape.is() && mpSvxShape ),
        "SdrObject::getSvxShape: still having IMPL-Pointer to dead object!" );
#endif
    //#113608#, make sure mpSvxShape is always synchronized with maWeakUnoShape
    if ( mpSvxShape && !xShape.is() )
        mpSvxShape = NULL;

	return mpSvxShape;
}

::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SdrObject::getUnoShape()
{
	// try weak reference first
	uno::Reference< uno::XInterface > xShape( getWeakUnoShape() );
	if( !xShape.is() )
	{
        OSL_ENSURE( mpSvxShape == NULL, "SdrObject::getUnoShape: XShape already dead, but still an IMPL pointer!" );
		if ( pPage )
		{
			uno::Reference< uno::XInterface > xPage( pPage->getUnoPage() );
			if( xPage.is() )
			{
				SvxDrawPage* pDrawPage = SvxDrawPage::getImplementation(xPage);
				if( pDrawPage )
				{
					// create one
                    xShape = pDrawPage->_CreateShape( this );
                    impl_setUnoShape( xShape );
				}
			}
		}
		else
		{
			mpSvxShape = SvxDrawPage::CreateShapeByTypeAndInventor( GetObjIdentifier(), GetObjInventor(), this, NULL );
			maWeakUnoShape = xShape = static_cast< ::cppu::OWeakObject* >( mpSvxShape );
		}
	}

	return xShape;
}

::svx::PropertyChangeNotifier& SdrObject::getShapePropertyChangeNotifier()
{
    DBG_TESTSOLARMUTEX();

    SvxShape* pSvxShape = getSvxShape();
    ENSURE_OR_THROW( pSvxShape, "no SvxShape, yet!" );
    return pSvxShape->getShapePropertyChangeNotifier();
}

void SdrObject::notifyShapePropertyChange( const ::svx::ShapeProperty _eProperty ) const
{
    DBG_TESTSOLARMUTEX();

    SvxShape* pSvxShape = const_cast< SdrObject* >( this )->getSvxShape();
    if ( pSvxShape )
        return pSvxShape->getShapePropertyChangeNotifier().notifyPropertyChange( _eProperty );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
//
// transformation interface for StarOfficeAPI. This implements support for
// homogen 3x3 matrices containing the transformation of the SdrObject. At the
// moment it contains a shearX, rotation and translation, but for setting all linear
// transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
//
////////////////////////////////////////////////////////////////////////////////////////////////////
// gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
// with the base geometry and returns TRUE. Otherwise it returns FALSE.
sal_Bool SdrObject::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
{
	// any kind of SdrObject, just use SnapRect
	Rectangle aRectangle(GetSnapRect());

	// convert to transformation 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
	const SfxMapUnit eMapUnit(GetObjectMapUnit());
	if(eMapUnit != SFX_MAPUNIT_100TH_MM)
	{
		switch(eMapUnit)
		{
			case SFX_MAPUNIT_TWIP :
			{
				// position
				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::createScaleTranslateB2DHomMatrix(aScale, aTranslate);

	return sal_False;
}

// sets the base geometry of the object using infos contained in the homogen 3x3 matrix.
// If it's an SdrPathObj it will use the provided geometry information. The Polygon has
// to use (0,0) as upper left and will be scaled to the given size in the matrix.
void SdrObject::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);
	}

	// force metric to pool metric
	const SfxMapUnit eMapUnit(GetObjectMapUnit());
	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 BaseRect
	Point aPoint(FRound(aTranslate.getX()), FRound(aTranslate.getY()));
	Rectangle aBaseRect(aPoint, Size(FRound(aScale.getX()), FRound(aScale.getY())));

	// set BaseRect
	SetSnapRect(aBaseRect);
}

// #116168#
// Give info if object is in destruction
sal_Bool SdrObject::IsInDestruction() const
{
	if(pModel)
		return pModel->IsInDestruction();
	return sal_False;
}

// return if fill is != XFILL_NONE
bool SdrObject::HasFillStyle() const
{
	return (((const XFillStyleItem&)GetObjectItem(XATTR_FILLSTYLE)).GetValue() != XFILL_NONE);
}

bool SdrObject::HasLineStyle() const
{
	return (((const XLineStyleItem&)GetObjectItem(XATTR_LINESTYLE)).GetValue() != XLINE_NONE);
}


// #i52224#
// on import of OLE object from MS documents the BLIP size might be retrieved,
// the following four methods are used to control it;
// usually this data makes no sence after the import is finished, since the object
// might be resized

Rectangle SdrObject::GetBLIPSizeRectangle() const
{
	return maBLIPSizeRectangle;
}

void SdrObject::SetBLIPSizeRectangle( const Rectangle& aRect )
{
	maBLIPSizeRectangle = aRect;
}

void SdrObject::SetContextWritingMode( const sal_Int16 /*_nContextWritingMode*/ )
{
    // this base class does not support different writing modes, so ignore the call
}

// #121917#
bool SdrObject::HasText() const
{
    return false;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
//
//   @@@@  @@@@@  @@@@@@  @@@@@  @@@@   @@@@  @@@@@@  @@@@  @@@@@  @@  @@
//  @@  @@ @@  @@     @@  @@    @@  @@ @@  @@   @@   @@  @@ @@  @@ @@  @@
//  @@  @@ @@  @@     @@  @@    @@  @@ @@       @@   @@  @@ @@  @@ @@  @@
//  @@  @@ @@@@@      @@  @@@@  @@@@@@ @@       @@   @@  @@ @@@@@   @@@@
//  @@  @@ @@  @@     @@  @@    @@  @@ @@       @@   @@  @@ @@  @@   @@
//  @@  @@ @@  @@ @@  @@  @@    @@  @@ @@  @@   @@   @@  @@ @@  @@   @@
//   @@@@  @@@@@   @@@@   @@    @@  @@  @@@@    @@    @@@@  @@  @@   @@
//
////////////////////////////////////////////////////////////////////////////////////////////////////

SdrObjFactory::SdrObjFactory(sal_uInt32 nInvent, sal_uInt16 nIdent, SdrPage* pNewPage, SdrModel* pNewModel)
{
	nInventor=nInvent;
	nIdentifier=nIdent;
	pNewObj=NULL;
	pPage=pNewPage;
	pModel=pNewModel;
	pObj=NULL;
	pNewData=NULL;
}

SdrObjFactory::SdrObjFactory(sal_uInt32 nInvent, sal_uInt16 nIdent, SdrObject* pObj1)
{
	nInventor=nInvent;
	nIdentifier=nIdent;
	pNewObj=NULL;
	pPage=NULL;
	pModel=NULL;
	pObj=pObj1;
	pNewData=NULL;
}

SdrObject* SdrObjFactory::MakeNewObject(sal_uInt32 nInvent, sal_uInt16 nIdent, SdrPage* pPage, SdrModel* pModel)
{
	if(pModel == NULL && pPage != NULL)
		pModel = pPage->GetModel();
	SdrObject* pObj = NULL;

	if(nInvent == SdrInventor)
	{
		switch (nIdent)
		{
			case sal_uInt16(OBJ_NONE       ): pObj=new SdrObject;                   break;
			case sal_uInt16(OBJ_GRUP       ): pObj=new SdrObjGroup;                 break;
			case sal_uInt16(OBJ_LINE       ): pObj=new SdrPathObj(OBJ_LINE       ); break;
			case sal_uInt16(OBJ_POLY       ): pObj=new SdrPathObj(OBJ_POLY       ); break;
			case sal_uInt16(OBJ_PLIN       ): pObj=new SdrPathObj(OBJ_PLIN       ); break;
			case sal_uInt16(OBJ_PATHLINE   ): pObj=new SdrPathObj(OBJ_PATHLINE   ); break;
			case sal_uInt16(OBJ_PATHFILL   ): pObj=new SdrPathObj(OBJ_PATHFILL   ); break;
			case sal_uInt16(OBJ_FREELINE   ): pObj=new SdrPathObj(OBJ_FREELINE   ); break;
			case sal_uInt16(OBJ_FREEFILL   ): pObj=new SdrPathObj(OBJ_FREEFILL   ); break;
			case sal_uInt16(OBJ_PATHPOLY   ): pObj=new SdrPathObj(OBJ_POLY       ); break;
			case sal_uInt16(OBJ_PATHPLIN   ): pObj=new SdrPathObj(OBJ_PLIN       ); break;
			case sal_uInt16(OBJ_EDGE       ): pObj=new SdrEdgeObj;                  break;
			case sal_uInt16(OBJ_RECT       ): pObj=new SdrRectObj;                  break;
			case sal_uInt16(OBJ_CIRC       ): pObj=new SdrCircObj(OBJ_CIRC       ); break;
			case sal_uInt16(OBJ_SECT       ): pObj=new SdrCircObj(OBJ_SECT       ); break;
			case sal_uInt16(OBJ_CARC       ): pObj=new SdrCircObj(OBJ_CARC       ); break;
			case sal_uInt16(OBJ_CCUT       ): pObj=new SdrCircObj(OBJ_CCUT       ); break;
			case sal_uInt16(OBJ_TEXT       ): pObj=new SdrRectObj(OBJ_TEXT       ); break;
			case sal_uInt16(OBJ_TEXTEXT    ): pObj=new SdrRectObj(OBJ_TEXTEXT    ); break;
			case sal_uInt16(OBJ_TITLETEXT  ): pObj=new SdrRectObj(OBJ_TITLETEXT  ); break;
			case sal_uInt16(OBJ_OUTLINETEXT): pObj=new SdrRectObj(OBJ_OUTLINETEXT); break;
			case sal_uInt16(OBJ_MEASURE    ): pObj=new SdrMeasureObj;               break;
			case sal_uInt16(OBJ_GRAF       ): pObj=new SdrGrafObj;                  break;
			case sal_uInt16(OBJ_OLE2       ): pObj=new SdrOle2Obj;                  break;
			case sal_uInt16(OBJ_FRAME      ): pObj=new SdrOle2Obj(sal_True);            break;
			case sal_uInt16(OBJ_CAPTION    ): pObj=new SdrCaptionObj;               break;
			case sal_uInt16(OBJ_PAGE       ): pObj=new SdrPageObj;                  break;
			case sal_uInt16(OBJ_UNO        ): pObj=new SdrUnoObj(String());			break;
			case sal_uInt16(OBJ_CUSTOMSHAPE  ): pObj=new SdrObjCustomShape();       break;
			case sal_uInt16(OBJ_MEDIA 	   ): pObj=new SdrMediaObj();           	break;
			case sal_uInt16(OBJ_TABLE	   ): pObj=new ::sdr::table::SdrTableObj(pModel);	break;
		}
	}

	if(pObj == NULL)
	{
		SdrObjFactory* pFact=new SdrObjFactory(nInvent,nIdent,pPage,pModel);
		SdrLinkList& rLL=ImpGetUserMakeObjHdl();
		unsigned nAnz=rLL.GetLinkCount();
		unsigned i=0;
		while (i<nAnz && pObj==NULL) {
			rLL.GetLink(i).Call((void*)pFact);
			pObj=pFact->pNewObj;
			i++;
		}
		delete pFact;
	}

	if(pObj == NULL)
	{
		// Na wenn's denn keiner will ...
	}

	if(pObj != NULL)
	{
		if(pPage != NULL)
			pObj->SetPage(pPage);
		else if(pModel != NULL)
			pObj->SetModel(pModel);
	}

	return pObj;
}

SdrObjUserData* SdrObjFactory::MakeNewObjUserData(sal_uInt32 nInvent, sal_uInt16 nIdent, SdrObject* pObj1)
{
	SdrObjUserData* pData=NULL;
	if (nInvent==SdrInventor) {
		switch (nIdent)
		{
			case sal_uInt16(SDRUSERDATA_OBJTEXTLINK) : pData=new ImpSdrObjTextLinkUserData((SdrTextObj*)pObj1); break;
		}
	}
	if (pData==NULL) {
		SdrObjFactory aFact(nInvent,nIdent,pObj1);
		SdrLinkList& rLL=ImpGetUserMakeObjUserDataHdl();
		unsigned nAnz=rLL.GetLinkCount();
		unsigned i=0;
		while (i<nAnz && pData==NULL) {
			rLL.GetLink(i).Call((void*)&aFact);
			pData=aFact.pNewData;
			i++;
		}
	}
	return pData;
}

void SdrObjFactory::InsertMakeObjectHdl(const Link& rLink)
{
	SdrLinkList& rLL=ImpGetUserMakeObjHdl();
	rLL.InsertLink(rLink);
}

void SdrObjFactory::RemoveMakeObjectHdl(const Link& rLink)
{
	SdrLinkList& rLL=ImpGetUserMakeObjHdl();
	rLL.RemoveLink(rLink);
}

void SdrObjFactory::InsertMakeUserDataHdl(const Link& rLink)
{
	SdrLinkList& rLL=ImpGetUserMakeObjUserDataHdl();
	rLL.InsertLink(rLink);
}

void SdrObjFactory::RemoveMakeUserDataHdl(const Link& rLink)
{
	SdrLinkList& rLL=ImpGetUserMakeObjUserDataHdl();
	rLL.RemoveLink(rLink);
}

namespace svx
{
    ISdrObjectFilter::~ISdrObjectFilter()
    {
    }
}

// eof
