text: /**************************************************************
   * 
   * 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"
  
  #define _ANIMATION
  #include <unotools/streamwrap.hxx>
  
  #include <sfx2/lnkbase.hxx>
  #include <math.h>
  #include <vcl/salbtype.hxx>
  #include <sot/formats.hxx>
  #include <sot/storage.hxx>
  #include <unotools/ucbstreamhelper.hxx>
  #include <unotools/localfilehelper.hxx>
  #include <svl/style.hxx>
  #include <svtools/filter.hxx>
  #include <svl/urihelper.hxx>
  #include <svtools/grfmgr.hxx>
  #include <vcl/svapp.hxx>
  
  #include <sfx2/linkmgr.hxx>
  #include <sfx2/docfile.hxx>
  #include <svx/svdetc.hxx>
  #include "svx/svdglob.hxx"
  #include "svx/svdstr.hrc"
  #include <svx/svdpool.hxx>
  #include <svx/svdmodel.hxx>
  #include <svx/svdpage.hxx>
  #include <svx/svdmrkv.hxx>
  #include <svx/svdpagv.hxx>
  #include "svx/svdviter.hxx"
  #include <svx/svdview.hxx>
  #include "svtools/filter.hxx"
  #include <svx/svdograf.hxx>
  #include <svx/svdogrp.hxx>
  #include <svx/xbtmpit.hxx>
  #include <svx/xflbmtit.hxx>
  #include <svx/svdundo.hxx>
  #include "svdfmtf.hxx"
  #include <svx/sdgcpitm.hxx>
  #include <editeng/eeitem.hxx>
  #include <svx/sdr/properties/graphicproperties.hxx>
  #include <svx/sdr/contact/viewcontactofgraphic.hxx>
  #include <basegfx/polygon/b2dpolygon.hxx>
  #include <basegfx/polygon/b2dpolygontools.hxx>
  #include <osl/thread.hxx>
  #include <vos/mutex.hxx>
  #include <drawinglayer/processor2d/objectinfoextractor2d.hxx>
  #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
  #include <unotools/cacheoptions.hxx>
  #include <basegfx/matrix/b2dhommatrixtools.hxx>
  
  using namespace ::com::sun::star::uno;
  using namespace ::com::sun::star::io;
  
  // -----------
  // - Defines -
  // -----------
  
  #define GRAFSTREAMPOS_INVALID   0xffffffff
  #define SWAPGRAPHIC_TIMEOUT     5000
  
  // #122985# it is not correct to se the swap-timeout to a hard-coded 5000ms as it was before.
  // Added code and experimented what to do as a good compromize, see description
  sal_uInt32 getCacheTimeInMs()
  {
      static bool bSetAtAll(true);
  
      if(bSetAtAll)
      {
          static bool bSetToPreferenceTime(true);
  
          if(bSetToPreferenceTime)
          {
              const SvtCacheOptions aCacheOptions;
              const sal_Int32 nSeconds(aCacheOptions.GetGraphicManagerObjectReleaseTime());
  
              // the default is 10 minutes. The minimum is one minute, thus 60 seconds. When the minimum
              // should match to the former hard-coded 5 seconds, we have a divisor of 12 to use. For the
              // default of 10 minutes this would mean 50 seconds. Compared to before this is ten times
              // more (would allow better navigation by switching through pages) and is controllable
              // by the user by setting the tools/options/memory/Remove_from_memory_after setting. Seems
              // to be a good compromize to me.
              return nSeconds * 1000 / 12;
          }
          else
          {
              return SWAPGRAPHIC_TIMEOUT;
          }
      }
  
      return 0;
  }
  
  // ------------------
  // - SdrGraphicLink	-
  // ------------------
  
  
  const Graphic ImpLoadLinkedGraphic( const String aFileName, const String aFilterName )
  {
  	Graphic aGraphic;
  
  	SfxMedium xMed( aFileName, STREAM_STD_READ, sal_True );
  	xMed.DownLoad();
  
  	SvStream* pInStrm = xMed.GetInStream();
  	if ( pInStrm )
  	{
  		pInStrm->Seek( STREAM_SEEK_TO_BEGIN );
  		GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
  
  		const sal_uInt16 nFilter = aFilterName.Len() && pGF->GetImportFormatCount()
  							? pGF->GetImportFormatNumber( aFilterName )
  							: GRFILTER_FORMAT_DONTKNOW;
  
  		com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aFilterData( 1 );
  
  		// Room for improvment:
  		// As this is a linked graphic the GfxLink is not needed if saving/loading our own format.
  		// But this link is required by some filters to access the native graphic (pdf export/ms export),
  		// there we should create a new service to provide this data if needed
  		aFilterData[ 0 ].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CreateNativeLink" ) );
  		aFilterData[ 0 ].Value = Any( sal_True );
  
          // #123042# for e.g SVG the path is needed, so hand it over here. I have no real idea
          // what consequences this may have; maybe this is not handed over by purpose here. Not
          // handing it over means that any GraphicFormat that internallv needs a path as base
          // to interpret included links may fail.
          // Alternatively the path may be set at the result after this call when it is known
          // that it is a SVG graphic, but only because no one yet tried to interpret it.
          pGF->ImportGraphic( aGraphic, aFileName, *pInStrm, nFilter, NULL, 0, &aFilterData );
  	}
  	return aGraphic;
  }
  
  class SdrGraphicUpdater;
  class SdrGraphicLink : public sfx2::SvBaseLink
  {
  	SdrGrafObj*			pGrafObj;
  	SdrGraphicUpdater*	pGraphicUpdater;
  
  public:
  						SdrGraphicLink(SdrGrafObj* pObj);
  	virtual				~SdrGraphicLink();
  
  	virtual void		Closed();
  	virtual void		DataChanged( const String& rMimeType,
  								const ::com::sun::star::uno::Any & rValue );
  	void				DataChanged( const Graphic& rGraphic );
  
  	sal_Bool				Connect() { return 0 != GetRealObject(); }
  	void				UpdateAsynchron();
  	void				RemoveGraphicUpdater();
  };
  
  class SdrGraphicUpdater : public ::osl::Thread
  {
  public:
      SdrGraphicUpdater( const String& rFileName, const String& rFilterName, SdrGraphicLink& );
      virtual ~SdrGraphicUpdater( void );
  
  	void SAL_CALL Terminate( void );
  
      sal_Bool GraphicLinkChanged( const String& rFileName ){ return maFileName != rFileName;	};
  
  protected:
  
  	/**	is called from the inherited create method and acts as the
  		main function of this thread.
  	*/
  	virtual void SAL_CALL run(void);
  
      /**	Called after the thread is terminated via the terminate
      	method.  Used to kill the thread by calling delete on this.
      */	
      virtual void SAL_CALL onTerminated(void);
  
  private:
  
      const String	maFileName;
  	const String	maFilterName;
  	SdrGraphicLink& mrGraphicLink;
  
  	volatile bool mbIsTerminated;
  };
  
  SdrGraphicUpdater::SdrGraphicUpdater( const String& rFileName, const String& rFilterName, SdrGraphicLink& rGraphicLink )
  : maFileName( rFileName )
  , maFilterName( rFilterName )
  , mrGraphicLink( rGraphicLink )
  , mbIsTerminated( sal_False )
  {
  	create();
  }
  
  SdrGraphicUpdater::~SdrGraphicUpdater( void )
  {
  }
  
  void SdrGraphicUpdater::Terminate()
  {
      mbIsTerminated = sal_True;
  }
  
  void SAL_CALL SdrGraphicUpdater::onTerminated(void)
  {
  	delete this;
  }
  
  void SAL_CALL SdrGraphicUpdater::run(void)
  {
  	Graphic aGraphic( ImpLoadLinkedGraphic( maFileName, maFilterName ) );
  	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
  	if ( !mbIsTerminated )
  	{
  		mrGraphicLink.DataChanged( aGraphic );
  		mrGraphicLink.RemoveGraphicUpdater();
  	}
  }
  
  // -----------------------------------------------------------------------------
  
  SdrGraphicLink::SdrGraphicLink(SdrGrafObj* pObj)
  : ::sfx2::SvBaseLink( ::sfx2::LINKUPDATE_ONCALL, SOT_FORMATSTR_ID_SVXB )
  , pGrafObj( pObj )
  , pGraphicUpdater( NULL )
  {
  	SetSynchron( sal_False );
  }
  
  // -----------------------------------------------------------------------------
  
  SdrGraphicLink::~SdrGraphicLink()
  {
  	if ( pGraphicUpdater )
  		pGraphicUpdater->Terminate();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGraphicLink::DataChanged( const Graphic& rGraphic )
  {
  	pGrafObj->ImpSetLinkedGraphic( rGraphic );
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGraphicLink::RemoveGraphicUpdater()
  {
  	pGraphicUpdater = NULL;
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGraphicLink::DataChanged( const String& rMimeType,
  								const ::com::sun::star::uno::Any & rValue )
  {
  	SdrModel*       pModel      = pGrafObj ? pGrafObj->GetModel() : 0;
  	sfx2::LinkManager* pLinkManager= pModel  ? pModel->GetLinkManager() : 0;
  
  	if( pLinkManager && rValue.hasValue() )
  	{
  		pLinkManager->GetDisplayNames( this, 0, &pGrafObj->aFileName, 0, &pGrafObj->aFilterName );
  
  		Graphic aGraphic;
  		if( sfx2::LinkManager::GetGraphicFromAny( rMimeType, rValue, aGraphic ))
  		{
     			pGrafObj->NbcSetGraphic( aGraphic );
  			pGrafObj->ActionChanged();
  		}
  		else if( SotExchange::GetFormatIdFromMimeType( rMimeType ) != sfx2::LinkManager::RegisterStatusInfoId() )
  		{
  			// broadcasting, to update slidesorter
  			pGrafObj->BroadcastObjectChange();
  		}
  	}
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGraphicLink::Closed()
  {
  	// Die Verbindung wird aufgehoben; pLink des Objekts auf NULL setzen, da die Link-Instanz ja gerade destruiert wird.
  	pGrafObj->ForceSwapIn();
  	pGrafObj->pGraphicLink=NULL;
  	pGrafObj->ReleaseGraphicLink();
  	SvBaseLink::Closed();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGraphicLink::UpdateAsynchron()
  {
  	if( GetObj() )
  	{
  		if ( pGraphicUpdater )
  		{
  			if ( pGraphicUpdater->GraphicLinkChanged( pGrafObj->GetFileName() ) )
  			{
  				pGraphicUpdater->Terminate();
  				pGraphicUpdater = new SdrGraphicUpdater( pGrafObj->GetFileName(), pGrafObj->GetFilterName(), *this );
  			}
  		}
  		else
  			pGraphicUpdater = new SdrGraphicUpdater( pGrafObj->GetFileName(), pGrafObj->GetFilterName(), *this );
  	}
  }
  
  // --------------
  // - SdrGrafObj -
  // --------------
  
  //////////////////////////////////////////////////////////////////////////////
  // BaseProperties section
  
  sdr::properties::BaseProperties* SdrGrafObj::CreateObjectSpecificProperties()
  {
  	return new sdr::properties::GraphicProperties(*this);
  }
  
  //////////////////////////////////////////////////////////////////////////////
  // DrawContact section
  
  sdr::contact::ViewContact* SdrGrafObj::CreateObjectSpecificViewContact()
  {
  	return new sdr::contact::ViewContactOfGraphic(*this);
  }
  
  //////////////////////////////////////////////////////////////////////////////
  // check if SVG and if try to get ObjectInfoPrimitive2D and extract info
  
  void SdrGrafObj::onGraphicChanged()
  {
      String aName;
      String aTitle;
      String aDesc;
  
      if(pGraphic)
      {
          const SvgDataPtr& rSvgDataPtr = pGraphic->GetGraphic().getSvgData();
  
          if(rSvgDataPtr.get())
          {
              const drawinglayer::primitive2d::Primitive2DSequence aSequence(rSvgDataPtr->getPrimitive2DSequence());
  
              if(aSequence.hasElements())
              {
                  drawinglayer::geometry::ViewInformation2D aViewInformation2D;
                  drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D aProcessor(aViewInformation2D);
  
                  aProcessor.process(aSequence);
  
                  const drawinglayer::primitive2d::ObjectInfoPrimitive2D* pResult = aProcessor.getResult();
  
                  if(pResult)
                  {
                      aName = pResult->getName();
  			        aTitle = pResult->getTitle();
  			        aDesc = pResult->getDesc();
                  }
              }
          }
      }
  
      if(aName.Len())
      {
          SetName(aName);
      }
  
      if(aTitle.Len())
      {
      	SetTitle(aTitle);
      }
  
      if(aDesc.Len())
      {
      	SetDescription(aDesc);
      }
  }
  
  //////////////////////////////////////////////////////////////////////////////
  
  TYPEINIT1(SdrGrafObj,SdrRectObj);
  
  // -----------------------------------------------------------------------------
  
  SdrGrafObj::SdrGrafObj()
  :	SdrRectObj(),
  	pGraphicLink	( NULL ),
  	bMirrored		( sal_False )
  {
  	pGraphic = new GraphicObject;
      mpReplacementGraphic = 0;
  	pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), getCacheTimeInMs() );
      onGraphicChanged();
  	
      // #i118485# Shear allowed and possible now
      bNoShear = false;
  
  	// #111096#
  	mbGrafAnimationAllowed = sal_True;
  
  	// #i25616#
  	mbLineIsOutsideGeometry = sal_True;
  	mbInsidePaint = sal_False;
  	mbIsPreview = sal_False;
  
  	// #i25616#
  	mbSupportTextIndentingOnLineWidthChange = sal_False;
  }
  
  // -----------------------------------------------------------------------------
  
  SdrGrafObj::SdrGrafObj(const Graphic& rGrf, const Rectangle& rRect)
  :	SdrRectObj		( rRect ),
  	pGraphicLink	( NULL ),
  	bMirrored		( sal_False )
  {
  	pGraphic = new GraphicObject( rGrf );
      mpReplacementGraphic = 0;
  	pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), getCacheTimeInMs() );
      onGraphicChanged();
  
      // #i118485# Shear allowed and possible now
      bNoShear = false;
  
  	// #111096#
  	mbGrafAnimationAllowed = sal_True;
  
  	// #i25616#
  	mbLineIsOutsideGeometry = sal_True;
  	mbInsidePaint = sal_False;
  	mbIsPreview	= sal_False;
  
  	// #i25616#
  	mbSupportTextIndentingOnLineWidthChange = sal_False;
  }
  
  // -----------------------------------------------------------------------------
  
  SdrGrafObj::SdrGrafObj( const Graphic& rGrf )
  :	SdrRectObj(),
  	pGraphicLink	( NULL ),
  	bMirrored		( sal_False )
  {
  	pGraphic = new GraphicObject( rGrf );
      mpReplacementGraphic = 0;
  	pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), getCacheTimeInMs() );
      onGraphicChanged();
  
      // #i118485# Shear allowed and possible now
      bNoShear = false;
  
  	// #111096#
  	mbGrafAnimationAllowed = sal_True;
  
  	// #i25616#
  	mbLineIsOutsideGeometry = sal_True;
  	mbInsidePaint = sal_False;
  	mbIsPreview	= sal_False;
  
  	// #i25616#
  	mbSupportTextIndentingOnLineWidthChange = sal_False;
  }
  
  // -----------------------------------------------------------------------------
  
  SdrGrafObj::~SdrGrafObj()
  {
  	delete pGraphic;
      delete mpReplacementGraphic;
  	ImpLinkAbmeldung();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::SetGraphicObject( const GraphicObject& rGrfObj )
  {
  	*pGraphic = rGrfObj;
      delete mpReplacementGraphic;
      mpReplacementGraphic = 0;
  	pGraphic->SetSwapStreamHdl( LINK( this, SdrGrafObj, ImpSwapHdl ), getCacheTimeInMs() );
  	pGraphic->SetUserData();
  	mbIsPreview = sal_False;
  	SetChanged();
  	BroadcastObjectChange();
      onGraphicChanged();
  }
  
  // -----------------------------------------------------------------------------
  
  const GraphicObject& SdrGrafObj::GetGraphicObject(bool bForceSwapIn) const
  {
  	if(bForceSwapIn)
  	{
  		ForceSwapIn();
  	}
  
  	return *pGraphic;
  }
  
  const GraphicObject* SdrGrafObj::GetReplacementGraphicObject() const
  {
      if(!mpReplacementGraphic && pGraphic)
      {
          const SvgDataPtr& rSvgDataPtr = pGraphic->GetGraphic().getSvgData();
  
          if(rSvgDataPtr.get())
          {
              const_cast< SdrGrafObj* >(this)->mpReplacementGraphic = new GraphicObject(rSvgDataPtr->getReplacement());
          }
      }
  
      return mpReplacementGraphic;
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::NbcSetGraphic( const Graphic& rGrf )
  {
  	pGraphic->SetGraphic( rGrf );
      delete mpReplacementGraphic;
      mpReplacementGraphic = 0;
  	pGraphic->SetUserData();
  	mbIsPreview = sal_False;
      onGraphicChanged();
  }
  
  void SdrGrafObj::SetGraphic( const Graphic& rGrf )
  {
      NbcSetGraphic(rGrf);
  	SetChanged();
  	BroadcastObjectChange();
  }
  
  // -----------------------------------------------------------------------------
  
  const Graphic& SdrGrafObj::GetGraphic() const
  {
  	ForceSwapIn();
  	return pGraphic->GetGraphic();
  }
  
  // -----------------------------------------------------------------------------
  
  Graphic SdrGrafObj::GetTransformedGraphic( sal_uIntPtr nTransformFlags ) const
  {
      // #107947# Refactored most of the code to GraphicObject, where
      // everybody can use e.g. the cropping functionality
  
  	GraphicType	    eType = GetGraphicType();
      MapMode   		aDestMap( pModel->GetScaleUnit(), Point(), pModel->GetScaleFraction(), pModel->GetScaleFraction() );
      const Size      aDestSize( GetLogicRect().GetSize() );
      const sal_Bool      bMirror = ( nTransformFlags & SDRGRAFOBJ_TRANSFORMATTR_MIRROR ) != 0;
      const sal_Bool      bRotate = ( ( nTransformFlags & SDRGRAFOBJ_TRANSFORMATTR_ROTATE ) != 0 ) &&
          ( aGeo.nDrehWink && aGeo.nDrehWink != 18000 ) && ( GRAPHIC_NONE != eType );
  
      // #104115# Need cropping info earlier
      ( (SdrGrafObj*) this )->ImpSetAttrToGrafInfo();
      GraphicAttr aActAttr;
  
  	if( SDRGRAFOBJ_TRANSFORMATTR_NONE != nTransformFlags &&
          GRAPHIC_NONE != eType )
  	{
          // actually transform the graphic only in this case. On the
          // other hand, cropping will always happen
          aActAttr = aGrafInfo;
  
          if( bMirror )
  		{
  			sal_uInt16		nMirrorCase = ( aGeo.nDrehWink == 18000 ) ? ( bMirrored ? 3 : 4 ) : ( bMirrored ? 2 : 1 );
  			FASTBOOL	bHMirr = nMirrorCase == 2 || nMirrorCase == 4;
  			FASTBOOL	bVMirr = nMirrorCase == 3 || nMirrorCase == 4;
  
  			aActAttr.SetMirrorFlags( ( bHMirr ? BMP_MIRROR_HORZ : 0 ) | ( bVMirr ? BMP_MIRROR_VERT : 0 ) );
  		}
  
  		if( bRotate )
  			aActAttr.SetRotation( sal_uInt16(aGeo.nDrehWink / 10) );
  	}
  
      // #107947# Delegate to moved code in GraphicObject
      return GetGraphicObject().GetTransformedGraphic( aDestSize, aDestMap, aActAttr );
  }
  
  // -----------------------------------------------------------------------------
  
  GraphicType SdrGrafObj::GetGraphicType() const
  {
  	return pGraphic->GetType();
  }
  
  sal_Bool SdrGrafObj::IsAnimated() const
  {
  	return pGraphic->IsAnimated();
  }
  
  sal_Bool SdrGrafObj::IsEPS() const
  {
  	return pGraphic->IsEPS();
  }
  
  sal_Bool SdrGrafObj::IsSwappedOut() const
  {
  	return mbIsPreview ? sal_True : pGraphic->IsSwappedOut();
  }
  
  const MapMode& SdrGrafObj::GetGrafPrefMapMode() const
  {
  	return pGraphic->GetPrefMapMode();
  }
  
  const Size& SdrGrafObj::GetGrafPrefSize() const
  {
  	return pGraphic->GetPrefSize();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::SetGrafStreamURL( const String& rGraphicStreamURL )
  {
  	mbIsPreview = sal_False;
  	if( !rGraphicStreamURL.Len() )
  	{
  		pGraphic->SetUserData();
  	}
  	else if( pModel->IsSwapGraphics() )
  	{
  		pGraphic->SetUserData( rGraphicStreamURL );
  
  		// set state of graphic object to 'swapped out'
  		if( pGraphic->GetType() == GRAPHIC_NONE )
  			pGraphic->SetSwapState();
  	}
  }
  
  // -----------------------------------------------------------------------------
  
  String SdrGrafObj::GetGrafStreamURL() const
  {
  	return pGraphic->GetUserData();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::SetFileName(const String& rFileName)
  {
  	aFileName = rFileName;
  	SetChanged();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::SetFilterName(const String& rFilterName)
  {
  	aFilterName = rFilterName;
  	SetChanged();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::ForceSwapIn() const
  {
  	if( mbIsPreview )
  	{
  		// removing preview graphic
  		const String aUserData( pGraphic->GetUserData() );
  
  		Graphic aEmpty;
  		pGraphic->SetGraphic( aEmpty );
  		pGraphic->SetUserData( aUserData );
  		pGraphic->SetSwapState();
  
  		const_cast< SdrGrafObj* >( this )->mbIsPreview = sal_False;
  	}
  	if ( pGraphicLink && pGraphic->IsSwappedOut() )
  		ImpUpdateGraphicLink( sal_False );
  	else
  		pGraphic->FireSwapInRequest();
  
  	if( pGraphic->IsSwappedOut() ||
  	    ( pGraphic->GetType() == GRAPHIC_NONE ) ||
  		( pGraphic->GetType() == GRAPHIC_DEFAULT ) )
  	{
  		Graphic aDefaultGraphic;
  		aDefaultGraphic.SetDefaultType();
  		pGraphic->SetGraphic( aDefaultGraphic );
  	}
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::ForceSwapOut() const
  {
  	pGraphic->FireSwapOutRequest();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::ImpLinkAnmeldung()
  {
  	sfx2::LinkManager* pLinkManager = pModel != NULL ? pModel->GetLinkManager() : NULL;
  
  	if( pLinkManager != NULL && pGraphicLink == NULL )
  	{
  		if( aFileName.Len() )
  		{
  			pGraphicLink = new SdrGraphicLink( this );
  			pLinkManager->InsertFileLink( *pGraphicLink, OBJECT_CLIENT_GRF, aFileName, ( aFilterName.Len() ? &aFilterName : NULL ), NULL );
  			pGraphicLink->Connect();
  		}
  	}
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::ImpLinkAbmeldung()
  {
  	sfx2::LinkManager* pLinkManager = pModel != NULL ? pModel->GetLinkManager() : NULL;
  
  	if( pLinkManager != NULL && pGraphicLink!=NULL)
  	{
  		// Bei Remove wird *pGraphicLink implizit deleted
  		pLinkManager->Remove( pGraphicLink );
  		pGraphicLink=NULL;
  	}
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::SetGraphicLink( const String& rFileName, const String& rFilterName )
  {
  	ImpLinkAbmeldung();
  	aFileName = rFileName;
  	aFilterName = rFilterName;
  	ImpLinkAnmeldung();
  	pGraphic->SetUserData();
  
      // #92205# A linked graphic is per definition swapped out (has to be loaded)
      pGraphic->SetSwapState();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::ReleaseGraphicLink()
  {
  	ImpLinkAbmeldung();
  	aFileName = String();
  	aFilterName = String();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
  {
  	FASTBOOL bNoPresGrf = ( pGraphic->GetType() != GRAPHIC_NONE ) && !bEmptyPresObj;
  
  	rInfo.bResizeFreeAllowed = aGeo.nDrehWink % 9000 == 0 ||
  							   aGeo.nDrehWink % 18000 == 0 ||
  							   aGeo.nDrehWink % 27000 == 0;
  
  	rInfo.bResizePropAllowed = sal_True;
  	rInfo.bRotateFreeAllowed = bNoPresGrf;
  	rInfo.bRotate90Allowed = bNoPresGrf;
  	rInfo.bMirrorFreeAllowed = bNoPresGrf;
  	rInfo.bMirror45Allowed = bNoPresGrf;
  	rInfo.bMirror90Allowed = !bEmptyPresObj;
  	rInfo.bTransparenceAllowed = sal_False;
  	rInfo.bGradientAllowed = sal_False;
  
      // #i118485# Shear allowed and possible now
  	rInfo.bShearAllowed = true;
  
      rInfo.bEdgeRadiusAllowed=sal_False;
  	rInfo.bCanConvToPath = !IsEPS();
  	rInfo.bCanConvToPathLineToArea = sal_False;
  	rInfo.bCanConvToPolyLineToArea = sal_False;
  	rInfo.bCanConvToPoly = !IsEPS();
  	rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
  }
  
  // -----------------------------------------------------------------------------
  
  sal_uInt16 SdrGrafObj::GetObjIdentifier() const
  {
  	return sal_uInt16( OBJ_GRAF );
  }
  
  // -----------------------------------------------------------------------------
  
  /* The graphic of the GraphicLink will be loaded. If it is called with
     bAsynchron = true then the graphic will be set later via DataChanged
  */ 
  sal_Bool SdrGrafObj::ImpUpdateGraphicLink( sal_Bool bAsynchron ) const
  {
      sal_Bool bRet = sal_False;
      if( pGraphicLink )
  	{
  		if ( bAsynchron )
  			pGraphicLink->UpdateAsynchron();
  		else
  			pGraphicLink->DataChanged( ImpLoadLinkedGraphic( aFileName, aFilterName ) );
          bRet = sal_True;
      }
  	return bRet;
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::ImpSetLinkedGraphic( const Graphic& rGraphic )
  {
  	const sal_Bool bIsChanged = GetModel()->IsChanged();
  	NbcSetGraphic( rGraphic );
  	ActionChanged();
  	BroadcastObjectChange();
  	GetModel()->SetChanged( bIsChanged );
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::TakeObjNameSingul(XubString& rName) const
  {
      if(pGraphic)
      {
          const SvgDataPtr& rSvgDataPtr = pGraphic->GetGraphic().getSvgData();
  
          if(rSvgDataPtr.get())
          {
              rName = ImpGetResStr(STR_ObjNameSingulGRAFSVG);
          }
          else
          {
  	        switch( pGraphic->GetType() )
  	        {
  		        case GRAPHIC_BITMAP:
                  {
                      const sal_uInt16 nId = ( ( pGraphic->IsTransparent() || ( (const SdrGrafTransparenceItem&) GetObjectItem( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() ) ?
                                           ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPTRANSLNK : STR_ObjNameSingulGRAFBMPTRANS ) :
                                           ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPLNK : STR_ObjNameSingulGRAFBMP ) );
  
                      rName=ImpGetResStr( nId );
                  }
                  break;
  
  		        case GRAPHIC_GDIMETAFILE:
                      rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNK : STR_ObjNameSingulGRAFMTF );
                  break;
  
                  case GRAPHIC_NONE:
                      rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNK : STR_ObjNameSingulGRAFNONE );
                  break;
  
                  default:
                      rName=ImpGetResStr(  IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNK : STR_ObjNameSingulGRAF );
                  break;
  	        }
          }
  
  	    const String aName(GetName());
  
  	    if( aName.Len() )
  	    {
  		    rName.AppendAscii( " '" );
  		    rName += aName;
  		    rName += sal_Unicode( '\'' );
  	    }
      }
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::TakeObjNamePlural( XubString& rName ) const
  {
      if(pGraphic)
      {
          const SvgDataPtr& rSvgDataPtr = pGraphic->GetGraphic().getSvgData();
  
          if(rSvgDataPtr.get())
          {
              rName = ImpGetResStr(STR_ObjNamePluralGRAFSVG);
          }
          else
          {
  	        switch( pGraphic->GetType() )
  	        {
  		        case GRAPHIC_BITMAP:
                  {
                      const sal_uInt16 nId = ( ( pGraphic->IsTransparent() || ( (const SdrGrafTransparenceItem&) GetObjectItem( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() ) ?
                                           ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPTRANSLNK : STR_ObjNamePluralGRAFBMPTRANS ) :
                                           ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPLNK : STR_ObjNamePluralGRAFBMP ) );
  
                      rName=ImpGetResStr( nId );
                  }
                  break;
  
  		        case GRAPHIC_GDIMETAFILE:
                      rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNK : STR_ObjNamePluralGRAFMTF );
                  break;
  
                  case GRAPHIC_NONE:
                      rName=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNK : STR_ObjNamePluralGRAFNONE );
                  break;
  
                  default:
                      rName=ImpGetResStr(  IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNK : STR_ObjNamePluralGRAF );
                  break;
  	        }
          }
  
  	    const String aName(GetName());
  
  	    if( aName.Len() )
  	    {
  		    rName.AppendAscii( " '" );
  		    rName += aName;
  		    rName += sal_Unicode( '\'' );
  	    }
      }
  }
  
  // -----------------------------------------------------------------------------
  
  SdrObject* SdrGrafObj::getFullDragClone() const
  {
      // call parent
      SdrGrafObj* pRetval = static_cast< SdrGrafObj* >(SdrRectObj::getFullDragClone());
  
      // #i103116# the full drag clone leads to problems
      // with linked graphics, so reset the link in this
      // temporary interaction object and load graphic
      if(pRetval && IsLinkedGraphic())
      {
          pRetval->ForceSwapIn();
          pRetval->ReleaseGraphicLink();
      }
  
      return pRetval;
  }
  
  void SdrGrafObj::operator=( const SdrObject& rObj )
  {
  	SdrRectObj::operator=( rObj );
  
  	const SdrGrafObj& rGraf = (SdrGrafObj&) rObj;
  
  	pGraphic->SetGraphic( rGraf.GetGraphic(), &rGraf.GetGraphicObject() );
  	aCropRect = rGraf.aCropRect;
  	aFileName = rGraf.aFileName;
  	aFilterName = rGraf.aFilterName;
  	bMirrored = rGraf.bMirrored;
  
  	if( rGraf.pGraphicLink != NULL)
  	{
  		SetGraphicLink( aFileName, aFilterName );
  	}
  
  	ImpSetAttrToGrafInfo();
  }
  
  // -----------------------------------------------------------------------------
  // #i25616#
  
  basegfx::B2DPolyPolygon SdrGrafObj::TakeXorPoly() const
  {
  	if(mbInsidePaint)
  	{
  		basegfx::B2DPolyPolygon aRetval;
  
  		// take grown rectangle
  		const sal_Int32 nHalfLineWidth(ImpGetLineWdt() / 2);
  		const Rectangle aGrownRect(
  			aRect.Left() - nHalfLineWidth,
  			aRect.Top() - nHalfLineWidth,
  			aRect.Right() + nHalfLineWidth,
  			aRect.Bottom() + nHalfLineWidth);
  
  		XPolygon aXPoly(ImpCalcXPoly(aGrownRect, GetEckenradius()));
  		aRetval.append(aXPoly.getB2DPolygon());
  
  		return aRetval;
  	}
  	else
  	{
  		// call parent
  		return SdrRectObj::TakeXorPoly();
  	}
  }
  
  // -----------------------------------------------------------------------------
  
  sal_uInt32 SdrGrafObj::GetHdlCount() const
  {
  	return 8L;
  }
  
  // -----------------------------------------------------------------------------
  
  SdrHdl* SdrGrafObj::GetHdl(sal_uInt32 nHdlNum) const
  {
  	return SdrRectObj::GetHdl( nHdlNum + 1L );
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
  {
  	SdrRectObj::NbcResize( rRef, xFact, yFact );
  
  	FASTBOOL bMirrX = xFact.GetNumerator() < 0;
  	FASTBOOL bMirrY = yFact.GetNumerator() < 0;
  
  	if( bMirrX != bMirrY )
  		bMirrored = !bMirrored;
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
  {
  	SdrRectObj::NbcRotate(rRef,nWink,sn,cs);
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::NbcMirror(const Point& rRef1, const Point& rRef2)
  {
  	SdrRectObj::NbcMirror(rRef1,rRef2);
  	bMirrored = !bMirrored;
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
  {
      // #i118485# Call Shear now, old version redirected to rotate
  	SdrRectObj::NbcShear(rRef, nWink, tn, bVShear);
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::NbcSetSnapRect(const Rectangle& rRect)
  {
  	SdrRectObj::NbcSetSnapRect(rRect);
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::NbcSetLogicRect( const Rectangle& rRect)
  {
  	//int bChg=rRect.GetSize()!=aRect.GetSize();
  	SdrRectObj::NbcSetLogicRect(rRect);
  }
  
  // -----------------------------------------------------------------------------
  
  SdrObjGeoData* SdrGrafObj::NewGeoData() const
  {
  	return new SdrGrafObjGeoData;
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::SaveGeoData(SdrObjGeoData& rGeo) const
  {
  	SdrRectObj::SaveGeoData(rGeo);
  	SdrGrafObjGeoData& rGGeo=(SdrGrafObjGeoData&)rGeo;
  	rGGeo.bMirrored=bMirrored;
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::RestGeoData(const SdrObjGeoData& rGeo)
  {
  	//long		nDrehMerk = aGeo.nDrehWink;
  	//long		nShearMerk = aGeo.nShearWink;
  	//int	bMirrMerk = bMirrored;
  	Size		aSizMerk( aRect.GetSize() );
  
  	SdrRectObj::RestGeoData(rGeo);
  	SdrGrafObjGeoData& rGGeo=(SdrGrafObjGeoData&)rGeo;
  	bMirrored=rGGeo.bMirrored;
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::SetPage( SdrPage* pNewPage )
  {
  	FASTBOOL bRemove = pNewPage == NULL && pPage != NULL;
  	FASTBOOL bInsert = pNewPage != NULL && pPage == NULL;
  
  	if( bRemove )
  	{
  		// hier kein SwapIn noetig, weil wenn nicht geladen, dann auch nicht animiert.
  		if( pGraphic->IsAnimated())
  			pGraphic->StopAnimation();
  
  		if( pGraphicLink != NULL )
  			ImpLinkAbmeldung();
  	}
  
      if(!pModel && !GetStyleSheet() && pNewPage->GetModel())
      {
          // #119287# Set default StyleSheet for SdrGrafObj here, it is different from 'Default'. This
          // needs to be done before the style 'Default' is set from the :SetModel() call which is triggered
          // from the following :SetPage().
          // TTTT: Needs to be moved in branch aw080 due to having a SdrModel from the beginning, is at this
          // place for convenience currently (works in both versions, is not in the way)
  		SfxStyleSheet* pSheet = pNewPage->GetModel()->GetDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj();
  
  		if(pSheet)
  		{
  			SetStyleSheet(pSheet, false);
  		}
          else
          {
  		    SetMergedItem(XFillStyleItem(XFILL_NONE));
  		    SetMergedItem(XLineStyleItem(XLINE_NONE));
          }
      }
  
  	SdrRectObj::SetPage( pNewPage );
  
  	if(aFileName.Len() && bInsert)
  		ImpLinkAnmeldung();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::SetModel( SdrModel* pNewModel )
  {
  	FASTBOOL bChg = pNewModel != pModel;
  
  	if( bChg )
  	{
  		if( pGraphic->HasUserData() )
  		{
  			ForceSwapIn();
  			pGraphic->SetUserData();
  		}
  
  		if( pGraphicLink != NULL )
  			ImpLinkAbmeldung();
  	}
  
  	// Model umsetzen
  	SdrRectObj::SetModel(pNewModel);
  
  	if( bChg && aFileName.Len() )
  		ImpLinkAnmeldung();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::StartAnimation( OutputDevice* /*pOutDev*/, const Point& /*rPoint*/, const Size& /*rSize*/, long /*nExtraData*/)
  {
  	// #111096#
  	// use new graf animation
  	SetGrafAnimationAllowed(sal_True);
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::StopAnimation(OutputDevice* /*pOutDev*/, long /*nExtraData*/)
  {
  	// #111096#
  	// use new graf animation
  	SetGrafAnimationAllowed(sal_False);
  }
  
  // -----------------------------------------------------------------------------
  
  FASTBOOL SdrGrafObj::HasGDIMetaFile() const
  {
  	return( pGraphic->GetType() == GRAPHIC_GDIMETAFILE );
  }
  
  // -----------------------------------------------------------------------------
  
  const GDIMetaFile* SdrGrafObj::GetGDIMetaFile() const
  {
  	DBG_ERROR( "Invalid return value! Don't use it! (KA)" );
  	return &GetGraphic().GetGDIMetaFile();
  }
  
  // -----------------------------------------------------------------------------
  
  bool SdrGrafObj::isEmbeddedSvg() const
  {
      return GRAPHIC_BITMAP == GetGraphicType() && GetGraphic().getSvgData().get();
  }
  
  GDIMetaFile SdrGrafObj::getMetafileFromEmbeddedSvg() const
  {
      GDIMetaFile aRetval;
  
      if(isEmbeddedSvg() && GetModel())
      {
          VirtualDevice aOut;
          const Rectangle aBoundRect(GetCurrentBoundRect());
          const MapMode aMap(GetModel()->GetScaleUnit(), Point(), GetModel()->GetScaleFraction(), GetModel()->GetScaleFraction());
  
          aOut.EnableOutput(false);
          aOut.SetMapMode(aMap);
          aRetval.Record(&aOut);
          SingleObjectPainter(aOut);
          aRetval.Stop();
          aRetval.WindStart();
          aRetval.Move(-aBoundRect.Left(), -aBoundRect.Top());
          aRetval.SetPrefMapMode(aMap);
          aRetval.SetPrefSize(aBoundRect.GetSize());
      }
  
      return aRetval;
  }
  
  SdrObject* SdrGrafObj::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const
  {
  	SdrObject* pRetval = NULL;
      GraphicType aGraphicType(GetGraphicType());
      GDIMetaFile aMtf;
  
      if(isEmbeddedSvg())
      {
          // Embedded Svg
          // There is currently no helper to create SdrObjects from primitives (even if I'm thinking
          // about writing one for some time). To get the roundtrip to SdrObjects it is necessary to
          // use the old converter path over the MetaFile mechanism. Create Metafile from Svg 
          // primitives here pretty directly
          aMtf = getMetafileFromEmbeddedSvg();
          aGraphicType = GRAPHIC_GDIMETAFILE;
      }
      else if(GRAPHIC_GDIMETAFILE == aGraphicType)
      {
          aMtf = GetTransformedGraphic(SDRGRAFOBJ_TRANSFORMATTR_COLOR|SDRGRAFOBJ_TRANSFORMATTR_MIRROR).GetGDIMetaFile();
      }
  
  	switch(aGraphicType)
  	{
  		case GRAPHIC_GDIMETAFILE:
  		{
  			// NUR die aus dem MetaFile erzeugbaren Objekte in eine Gruppe packen und zurueckliefern
  			ImpSdrGDIMetaFileImport aFilter(*GetModel(), GetLayer(), aRect);
  			SdrObjGroup* pGrp = new SdrObjGroup();
  			sal_uInt32 nInsAnz = aFilter.DoImport(aMtf, *pGrp->GetSubList(), 0);
  
              if(nInsAnz)
  			{
                  {
                          // copy transformation
                  	GeoStat aGeoStat(GetGeoStat());
  
  	                if(aGeoStat.nShearWink) 
                      {
                          aGeoStat.RecalcTan();
                          pGrp->NbcShear(aRect.TopLeft(), aGeoStat.nShearWink, aGeoStat.nTan, false);
                      }
  
  	                if(aGeoStat.nDrehWink) 
                      {
  	                    aGeoStat.RecalcSinCos();
                          pGrp->NbcRotate(aRect.TopLeft(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos);
                      }
                  }
  
                  pRetval = pGrp;
  				pGrp->NbcSetLayer(GetLayer());
  				pGrp->SetModel(GetModel());
                  
                  if(bAddText)
                  {
  				    pRetval = ImpConvertAddText(pRetval, bBezier);
                  }
  
                  // convert all children
                  if( pRetval )
                  {
                      SdrObject* pHalfDone = pRetval;
                      pRetval = pHalfDone->DoConvertToPolyObj(bBezier, bAddText);
                      SdrObject::Free( pHalfDone ); // resulting object is newly created
  
                      if( pRetval )
                      {
                          // flatten subgroups. As we call
                          // DoConvertToPolyObj() on the resulting group
                          // objects, subgroups can exist (e.g. text is
                          // a group object for every line).
                          SdrObjList* pList = pRetval->GetSubList();
                          if( pList )
                              pList->FlattenGroups();
                      }
                  }
  			}
  			else
              {
  				delete pGrp;
              }
  
              // #i118485# convert line and fill
              SdrObject* pLineFill = SdrRectObj::DoConvertToPolyObj(bBezier, false);
  
              if(pLineFill)
              {
                  if(pRetval)
                  {
                      pGrp = dynamic_cast< SdrObjGroup* >(pRetval);
  
                      if(!pGrp)
                      {
              			pGrp = new SdrObjGroup();
  
                          pGrp->NbcSetLayer(GetLayer());
  				        pGrp->SetModel(GetModel());
                          pGrp->GetSubList()->NbcInsertObject(pRetval);
                      }
  
                      pGrp->GetSubList()->NbcInsertObject(pLineFill, 0);
                  }
                  else
                  {
                      pRetval = pLineFill;
                  }
              }
  
  			break;
  		}
  		case GRAPHIC_BITMAP:
  		{
  			// Grundobjekt kreieren und Fuellung ergaenzen
  			pRetval = SdrRectObj::DoConvertToPolyObj(bBezier, bAddText);
  
  			// Bitmap als Attribut retten
  			if(pRetval)
  			{
  				// Bitmap als Fuellung holen
  				SfxItemSet aSet(GetObjectItemSet());
  
  				aSet.Put(XFillStyleItem(XFILL_BITMAP));
  				const BitmapEx aBitmapEx(GetTransformedGraphic().GetBitmapEx());
  				aSet.Put(XFillBitmapItem(String(), Graphic(aBitmapEx)));
  				aSet.Put(XFillBmpTileItem(false));
  
  				pRetval->SetMergedItemSet(aSet);
  			}
  			break;
  		}
  		case GRAPHIC_NONE:
  		case GRAPHIC_DEFAULT:
  		{
  			pRetval = SdrRectObj::DoConvertToPolyObj(bBezier, bAddText);
  			break;
  		}
  	}
  
  	return pRetval;
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
  {
  	SetXPolyDirty();
  	SdrRectObj::Notify( rBC, rHint );
  	ImpSetAttrToGrafInfo();
  }
  
  void SdrGrafObj::ImpSetAttrToGrafInfo()
  {
  	const SfxItemSet& rSet = GetObjectItemSet();
  	const sal_uInt16 nTrans = ( (SdrGrafTransparenceItem&) rSet.Get( SDRATTR_GRAFTRANSPARENCE ) ).GetValue();
  	const SdrGrafCropItem&	rCrop = (const SdrGrafCropItem&) rSet.Get( SDRATTR_GRAFCROP );
  
  	aGrafInfo.SetLuminance( ( (SdrGrafLuminanceItem&) rSet.Get( SDRATTR_GRAFLUMINANCE ) ).GetValue() );
  	aGrafInfo.SetContrast( ( (SdrGrafContrastItem&) rSet.Get( SDRATTR_GRAFCONTRAST ) ).GetValue() );
  	aGrafInfo.SetChannelR( ( (SdrGrafRedItem&) rSet.Get( SDRATTR_GRAFRED ) ).GetValue() );
  	aGrafInfo.SetChannelG( ( (SdrGrafGreenItem&) rSet.Get( SDRATTR_GRAFGREEN ) ).GetValue() );
  	aGrafInfo.SetChannelB( ( (SdrGrafBlueItem&) rSet.Get( SDRATTR_GRAFBLUE ) ).GetValue() );
  	aGrafInfo.SetGamma( ( (SdrGrafGamma100Item&) rSet.Get( SDRATTR_GRAFGAMMA ) ).GetValue() * 0.01 );
  	aGrafInfo.SetTransparency( (sal_uInt8) FRound( Min( nTrans, (sal_uInt16) 100 )  * 2.55 ) );
  	aGrafInfo.SetInvert( ( (SdrGrafInvertItem&) rSet.Get( SDRATTR_GRAFINVERT ) ).GetValue() );
  	aGrafInfo.SetDrawMode( ( (SdrGrafModeItem&) rSet.Get( SDRATTR_GRAFMODE ) ).GetValue() );
  	aGrafInfo.SetCrop( rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom() );
  
  	SetXPolyDirty();
  	SetRectsDirty();
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::ImpSetGrafInfoToAttr()
  {
  	SetObjectItem( SdrGrafLuminanceItem( aGrafInfo.GetLuminance() ) );
  	SetObjectItem( SdrGrafContrastItem( aGrafInfo.GetContrast() ) );
  	SetObjectItem( SdrGrafRedItem( aGrafInfo.GetChannelR() ) );
  	SetObjectItem( SdrGrafGreenItem( aGrafInfo.GetChannelG() ) );
  	SetObjectItem( SdrGrafBlueItem( aGrafInfo.GetChannelB() ) );
  	SetObjectItem( SdrGrafGamma100Item( FRound( aGrafInfo.GetGamma() * 100.0 ) ) );
  	SetObjectItem( SdrGrafTransparenceItem( (sal_uInt16) FRound( aGrafInfo.GetTransparency() / 2.55 ) ) );
  	SetObjectItem( SdrGrafInvertItem( aGrafInfo.IsInvert() ) );
  	SetObjectItem( SdrGrafModeItem( aGrafInfo.GetDrawMode() ) );
  	SetObjectItem( SdrGrafCropItem( aGrafInfo.GetLeftCrop(), aGrafInfo.GetTopCrop(), aGrafInfo.GetRightCrop(), aGrafInfo.GetBottomCrop() ) );
  }
  
  // -----------------------------------------------------------------------------
  
  void SdrGrafObj::AdjustToMaxRect( const Rectangle& rMaxRect, bool bShrinkOnly )
  {
  	Size aSize;
  	Size aMaxSize( rMaxRect.GetSize() );
  	if ( pGraphic->GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
  		aSize = Application::GetDefaultDevice()->PixelToLogic( pGraphic->GetPrefSize(), MAP_100TH_MM );
  	else
  		aSize = OutputDevice::LogicToLogic( pGraphic->GetPrefSize(),
  										    pGraphic->GetPrefMapMode(),
  										    MapMode( MAP_100TH_MM ) );
  
  	if( aSize.Height() != 0 && aSize.Width() != 0 )
  	{
  		Point aPos( rMaxRect.TopLeft() );
  
  		// Falls Grafik zu gross, wird die Grafik
  		// in die Seite eingepasst
  		if ( (!bShrinkOnly                          ||
  	    	 ( aSize.Height() > aMaxSize.Height() ) ||
  		 	( aSize.Width()  > aMaxSize.Width()  ) )&&
  		 	aSize.Height() && aMaxSize.Height() )
  		{
  			float fGrfWH =	(float)aSize.Width() /
  							(float)aSize.Height();
  			float fWinWH =	(float)aMaxSize.Width() /
  							(float)aMaxSize.Height();
  
  			// Grafik an Pagesize anpassen (skaliert)
  			if ( fGrfWH < fWinWH )
  			{
  				aSize.Width() = (long)(aMaxSize.Height() * fGrfWH);
  				aSize.Height()= aMaxSize.Height();
  			}
  			else if ( fGrfWH > 0.F )
  			{
  				aSize.Width() = aMaxSize.Width();
  				aSize.Height()= (long)(aMaxSize.Width() / fGrfWH);
  			}
  
  			aPos = rMaxRect.Center();
  		}
  
  		if( bShrinkOnly )
  			aPos = aRect.TopLeft();
  
  		aPos.X() -= aSize.Width() / 2;
  		aPos.Y() -= aSize.Height() / 2;
  		SetLogicRect( Rectangle( aPos, aSize ) );
  	}
  }
  
  // -----------------------------------------------------------------------------
  
  IMPL_LINK( SdrGrafObj, ImpSwapHdl, GraphicObject*, pO )
  {
  	SvStream* pRet = GRFMGR_AUTOSWAPSTREAM_NONE;
  
  	if( pO->IsInSwapOut() )
  	{
  		if( pModel && !mbIsPreview && pModel->IsSwapGraphics() && pGraphic->GetSizeBytes() > 20480 )
  		{
  			// test if this object is visualized from someone
              // ## test only if there are VOCs other than the preview renderer
  			if(!GetViewContact().HasViewObjectContacts(true))
  			{
  				const sal_uIntPtr	nSwapMode = pModel->GetSwapGraphicsMode();
  
  				if( ( pGraphic->HasUserData() || pGraphicLink ) &&
  					( nSwapMode & SDR_SWAPGRAPHICSMODE_PURGE ) )
  				{
  					pRet = GRFMGR_AUTOSWAPSTREAM_LINK;
  				}
  				else if( nSwapMode & SDR_SWAPGRAPHICSMODE_TEMP )
  				{
  					pRet = GRFMGR_AUTOSWAPSTREAM_TEMP;
  					pGraphic->SetUserData();
  				}
  
  				// #i102380#
  				sdr::contact::ViewContactOfGraphic* pVC = dynamic_cast< sdr::contact::ViewContactOfGraphic* >(&GetViewContact());
  
  				if(pVC)
  				{
  					pVC->flushGraphicObjects();
  				}
  			}
  		}
  	}
  	else if( pO->IsInSwapIn() )
  	{
  		// kann aus dem original Doc-Stream nachgeladen werden...
  		if( pModel != NULL )
  		{
  			if( pGraphic->HasUserData() )
  			{
  				SdrDocumentStreamInfo aStreamInfo;
  
  				aStreamInfo.mbDeleteAfterUse = sal_False;
  				aStreamInfo.maUserData = pGraphic->GetUserData();
  
  				SvStream* pStream = pModel->GetDocumentStream( aStreamInfo );
  
  				if( pStream != NULL )
  				{
  					Graphic aGraphic;
  
                      com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData = NULL;
                      
  					if(mbInsidePaint && !GetViewContact().HasViewObjectContacts(true))
                      {
                          pFilterData = new com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >( 3 );
  
                          const com::sun::star::awt::Size aPreviewSizeHint( 64, 64 );
                          const sal_Bool bAllowPartialStreamRead = sal_True;
                          // create <GfxLink> instance also for previews in order to avoid that its corresponding
                          // data is cleared in the graphic cache entry in case that the preview data equals the complete graphic data
                          const sal_Bool bCreateNativeLink = sal_True;
                          (*pFilterData)[ 0 ].Name = String( RTL_CONSTASCII_USTRINGPARAM( "PreviewSizeHint" ) );
                          (*pFilterData)[ 0 ].Value <<= aPreviewSizeHint;
                          (*pFilterData)[ 1 ].Name = String( RTL_CONSTASCII_USTRINGPARAM( "AllowPartialStreamRead" ) );
                          (*pFilterData)[ 1 ].Value <<= bAllowPartialStreamRead;
                          (*pFilterData)[ 2 ].Name = String( RTL_CONSTASCII_USTRINGPARAM( "CreateNativeLink" ) );
                          (*pFilterData)[ 2 ].Value <<= bCreateNativeLink;
  
                          mbIsPreview = sal_True;
                      }
  
                      if(!GraphicFilter::GetGraphicFilter()->ImportGraphic(
                          aGraphic, aStreamInfo.maUserData, *pStream,
                          GRFILTER_FORMAT_DONTKNOW, NULL, 0, pFilterData))
                      {
                          const String aUserData( pGraphic->GetUserData() );
  
                          pGraphic->SetGraphic( aGraphic );
                          pGraphic->SetUserData( aUserData );
  
                          // #142146# Graphic successfully swapped in.
                          pRet = GRFMGR_AUTOSWAPSTREAM_LOADED;
                      }
                      delete pFilterData;
  
                      pStream->ResetError();
  
                      if( aStreamInfo.mbDeleteAfterUse || aStreamInfo.mxStorageRef.is() )
                      {
                          if ( aStreamInfo.mxStorageRef.is() )
                          {
                              aStreamInfo.mxStorageRef->dispose();
                              aStreamInfo.mxStorageRef = 0;
                          }
  
                          delete pStream;
                      }
                  }
  			}
  			else if( !ImpUpdateGraphicLink( sal_False ) )
              {
  				pRet = GRFMGR_AUTOSWAPSTREAM_TEMP;
              }
  			else
              {
                  pRet = GRFMGR_AUTOSWAPSTREAM_LOADED;
              }
  		}
  		else
  			pRet = GRFMGR_AUTOSWAPSTREAM_TEMP;
  	}
  
  	return (long)(void*) pRet;
  }
  
  // -----------------------------------------------------------------------------
  
  // #111096#
  // Access to GrafAnimationAllowed flag
  sal_Bool SdrGrafObj::IsGrafAnimationAllowed() const
  {
  	return mbGrafAnimationAllowed;
  }
  
  void SdrGrafObj::SetGrafAnimationAllowed(sal_Bool bNew)
  {
  	if(mbGrafAnimationAllowed != bNew)
  	{
  		mbGrafAnimationAllowed = bNew;
  		ActionChanged();
  	}
  }
  
  // #i25616#
  sal_Bool SdrGrafObj::IsObjectTransparent() const
  {
  	if(((const SdrGrafTransparenceItem&)GetObjectItem(SDRATTR_GRAFTRANSPARENCE)).GetValue()
  		|| pGraphic->IsTransparent())
  	{
  		return sal_True;
  	}
  
  	return sal_False;
  }
  
  Reference< XInputStream > SdrGrafObj::getInputStream()
  {
  	Reference< XInputStream > xStream;
  
  	if( pModel )
  	{
  //		if( !pGraphic->HasUserData() )
  //			pGraphic->SwapOut();
  
  		// kann aus dem original Doc-Stream nachgeladen werden...
  		if( pGraphic->HasUserData() )
  		{
  			SdrDocumentStreamInfo aStreamInfo;
  
  			aStreamInfo.mbDeleteAfterUse = sal_False;
  			aStreamInfo.maUserData = pGraphic->GetUserData();
  
  			SvStream* pStream = pModel->GetDocumentStream( aStreamInfo );
  
  			if( pStream )
  				xStream.set( new utl::OInputStreamWrapper( pStream, sal_True ) );
  		}
  		else if( pGraphic && GetGraphic().IsLink() )
  		{
  			Graphic aGraphic( GetGraphic() );
  			GfxLink aLink( aGraphic.GetLink() );
  			sal_uInt32 nSize = aLink.GetDataSize();
  			const void* pSourceData = (const void*)aLink.GetData();
  			if( nSize && pSourceData )
  			{
  				sal_uInt8 * pBuffer = new sal_uInt8[ nSize ];
  				if( pBuffer )
  				{
  					memcpy( pBuffer, pSourceData, nSize );
  
  					SvMemoryStream* pStream = new SvMemoryStream( (void*)pBuffer, (sal_Size)nSize, STREAM_READ );
  					pStream->ObjectOwnsMemory( sal_True );
  					xStream.set( new utl::OInputStreamWrapper( pStream, sal_True ) );
  				}
  			}
  		}
  
  		if( !xStream.is() && aFileName.Len() )
  		{
  			SvFileStream* pStream = new SvFileStream( aFileName, STREAM_READ );
  			if( pStream )
  				xStream.set( new utl::OInputStreamWrapper( pStream ) );
  		}
  	}
  
  	return xStream;
  }
  
  // moved crop handle creation here; this is the object type using them
  void SdrGrafObj::addCropHandles(SdrHdlList& rTarget) const
  {
      basegfx::B2DHomMatrix aMatrix;
      basegfx::B2DPolyPolygon aPolyPolygon;
  
      // get object transformation
      TRGetBaseGeometry(aMatrix, aPolyPolygon);
  
      // part of object transformation correction, but used later, so defined outside next scope
      double fShearX(0.0), fRotate(0.0);
  
      {   // TTTT correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080
          basegfx::B2DTuple aScale;
          basegfx::B2DTuple aTranslate;
  
          aMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
  
          if(!basegfx::fTools::equalZero(fShearX))
          {
              // shearX is used, correct it
              fShearX = -fShearX;
          }
  
          aMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
              aScale,
              fShearX,
              fRotate,
              aTranslate);
      }
  
      // get crop values
      const SdrGrafCropItem& rCrop = static_cast< const SdrGrafCropItem& >(GetMergedItem(SDRATTR_GRAFCROP));
  
      if(rCrop.GetLeft() || rCrop.GetTop() || rCrop.GetRight() ||rCrop.GetBottom())
      {
          // decompose object transformation to have current translate and scale
          basegfx::B2DVector aScale, aTranslate;
          double fRotate, fShearX;
  
          aMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
  
          if(!aScale.equalZero())
          {
              // get crop scale
              const basegfx::B2DVector aCropScaleFactor(
                  GetGraphicObject().calculateCropScaling(
                      aScale.getX(),
                      aScale.getY(),
                      rCrop.GetLeft(),
                      rCrop.GetTop(),
                      rCrop.GetRight(),
                      rCrop.GetBottom()));
  
              // apply crop scale
              const double fCropLeft(rCrop.GetLeft() * aCropScaleFactor.getX());
              const double fCropTop(rCrop.GetTop() * aCropScaleFactor.getY());
              const double fCropRight(rCrop.GetRight() * aCropScaleFactor.getX());
              const double fCropBottom(rCrop.GetBottom() * aCropScaleFactor.getY());
              basegfx::B2DHomMatrix aMatrixForCropViewHdl(aMatrix);
  
              if(IsMirrored())
              {
                  // create corrected new matrix, TTTT can be removed with aw080
                  // the old mirror only can mirror horizontally; the vertical mirror
                  // is faked by using the horizontal and 180 degree rotation. Since
                  // the object can be rotated differently from 180 degree, this is
                  // not safe to detect. Just correct horizontal mirror (which is
                  // in IsMirrored()) and keep the rotation angle
                  // caution: Do not modify aMatrix, it is used below to calculate
                  // the exact handle positions
                  basegfx::B2DHomMatrix aPreMultiply;
  
                  // mirrored X, apply
                  aPreMultiply.translate(-0.5, 0.0);
                  aPreMultiply.scale(-1.0, 1.0);
                  aPreMultiply.translate(0.5, 0.0);
  
                  aMatrixForCropViewHdl = aMatrixForCropViewHdl * aPreMultiply;
              }
  
              rTarget.AddHdl(
                  new SdrCropViewHdl(
                      aMatrixForCropViewHdl,
                      GetGraphicObject().GetGraphic(),
                      fCropLeft,
                      fCropTop,
                      fCropRight,
                      fCropBottom));
          }
      }
  
      basegfx::B2DPoint aPos;
  
      aPos = aMatrix * basegfx::B2DPoint(0.0, 0.0); 
      rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_UPLFT, fShearX, fRotate));
      aPos = aMatrix * basegfx::B2DPoint(0.5, 0.0); 
      rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_UPPER, fShearX, fRotate));
      aPos = aMatrix * basegfx::B2DPoint(1.0, 0.0); 
      rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_UPRGT, fShearX, fRotate));
      aPos = aMatrix * basegfx::B2DPoint(0.0, 0.5); 
      rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_LEFT , fShearX, fRotate));
      aPos = aMatrix * basegfx::B2DPoint(1.0, 0.5); 
      rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_RIGHT, fShearX, fRotate));
      aPos = aMatrix * basegfx::B2DPoint(0.0, 1.0); 
      rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_LWLFT, fShearX, fRotate));
      aPos = aMatrix * basegfx::B2DPoint(0.5, 1.0); 
      rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_LOWER, fShearX, fRotate));
      aPos = aMatrix * basegfx::B2DPoint(1.0, 1.0); 
      rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), HDL_LWRGT, fShearX, fRotate));
  }
  
  // eof
  