office-gobmx/svx/source/svdraw/svdograf.cxx
Tor Lillqvist 8e7897588d Rename the basegfx::tools namespace to basegfx::utils
Reduce potential confusion with the global tools namespace. Will
hopefully make it possible to remove the annoying initial :: when
referring to the global tools namespace. Unless we have even more
tools subnamespaces somewhere.

Thorsten said it was OK.

Change-Id: Id088dfe8f4244cb79df9aa988995b31a1758c996
Reviewed-on: https://gerrit.libreoffice.org/42644
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Tor Lillqvist <tml@collabora.com>
2017-09-26 14:18:41 +02:00

1615 lines
51 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* 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 .
*/
#include <unotools/streamwrap.hxx>
#include <sfx2/lnkbase.hxx>
#include <math.h>
#include <tools/helpers.hxx>
#include <sot/formats.hxx>
#include <sot/storage.hxx>
#include <comphelper/storagehelper.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/localfilehelper.hxx>
#include <svl/style.hxx>
#include <vcl/graphicfilter.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 "svdglob.hxx"
#include "svx/strings.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 <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 <sdr/properties/graphicproperties.hxx>
#include <sdr/contact/viewcontactofgraphic.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <osl/thread.hxx>
#include <drawinglayer/processor2d/objectinfoextractor2d.hxx>
#include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
#include <memory>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::io;
const Graphic ImpLoadLinkedGraphic( const OUString& aFileName, const OUString& aReferer, const OUString& aFilterName )
{
Graphic aGraphic;
SfxMedium aMed( aFileName, aReferer, StreamMode::STD_READ );
aMed.Download();
SvStream* pInStrm = aMed.GetInStream();
if ( pInStrm )
{
pInStrm->Seek( STREAM_SEEK_TO_BEGIN );
GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
const sal_uInt16 nFilter = !aFilterName.isEmpty() && rGF.GetImportFormatCount()
? rGF.GetImportFormatNumber( aFilterName )
: GRFILTER_FORMAT_DONTKNOW;
css::uno::Sequence< css::beans::PropertyValue > aFilterData( 1 );
// TODO: Room for improvement:
// 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 = "CreateNativeLink";
aFilterData[ 0 ].Value <<= true;
// #i123042# 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 internally 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.
rGF.ImportGraphic( aGraphic, aFileName, *pInStrm, nFilter, nullptr, GraphicFilterImportFlags::NONE, &aFilterData );
}
return aGraphic;
}
class SdrGraphicUpdater;
class SdrGraphicLink : public sfx2::SvBaseLink
{
SdrGrafObj& rGrafObj;
SdrGraphicUpdater* pGraphicUpdater;
public:
explicit SdrGraphicLink(SdrGrafObj& rObj);
virtual ~SdrGraphicLink() override;
virtual void Closed() override;
virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
const OUString& rMimeType, const css::uno::Any & rValue ) override;
void DataChanged( const Graphic& rGraphic );
void Connect() { GetRealObject(); }
void UpdateAsynchron();
void RemoveGraphicUpdater();
const OUString& getReferer() const { return rGrafObj.aReferer; }
};
class SdrGraphicUpdater : public ::osl::Thread
{
public:
SdrGraphicUpdater( const OUString& rFileName, const OUString& rFilterName, SdrGraphicLink& );
void SAL_CALL Terminate();
bool GraphicLinkChanged( const OUString& 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() override;
/** 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() override;
private:
const OUString maFileName;
const OUString maFilterName;
SdrGraphicLink& mrGraphicLink;
volatile bool mbIsTerminated;
};
SdrGraphicUpdater::SdrGraphicUpdater( const OUString& rFileName, const OUString& rFilterName, SdrGraphicLink& rGraphicLink )
: maFileName( rFileName )
, maFilterName( rFilterName )
, mrGraphicLink( rGraphicLink )
, mbIsTerminated( false )
{
create();
}
void SdrGraphicUpdater::Terminate()
{
mbIsTerminated = true;
}
void SAL_CALL SdrGraphicUpdater::onTerminated()
{
delete this;
}
void SAL_CALL SdrGraphicUpdater::run()
{
osl_setThreadName("SdrGraphicUpdater");
Graphic aGraphic( ImpLoadLinkedGraphic( maFileName, mrGraphicLink.getReferer(), maFilterName ) );
SolarMutexGuard aSolarGuard;
if ( !mbIsTerminated )
{
mrGraphicLink.DataChanged( aGraphic );
mrGraphicLink.RemoveGraphicUpdater();
}
}
SdrGraphicLink::SdrGraphicLink(SdrGrafObj& rObj)
: ::sfx2::SvBaseLink( ::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB )
, rGrafObj( rObj )
, pGraphicUpdater( nullptr )
{
SetSynchron( false );
}
SdrGraphicLink::~SdrGraphicLink()
{
if ( pGraphicUpdater )
pGraphicUpdater->Terminate();
}
void SdrGraphicLink::DataChanged( const Graphic& rGraphic )
{
rGrafObj.ImpSetLinkedGraphic( rGraphic );
}
void SdrGraphicLink::RemoveGraphicUpdater()
{
pGraphicUpdater = nullptr;
}
::sfx2::SvBaseLink::UpdateResult SdrGraphicLink::DataChanged(
const OUString& rMimeType, const css::uno::Any & rValue )
{
SdrModel* pModel = rGrafObj.GetModel();
sfx2::LinkManager* pLinkManager= pModel ? pModel->GetLinkManager() : nullptr;
if( pLinkManager && rValue.hasValue() )
{
sfx2::LinkManager::GetDisplayNames( this, nullptr, &rGrafObj.aFileName, nullptr, &rGrafObj.aFilterName );
Graphic aGraphic;
if( sfx2::LinkManager::GetGraphicFromAny( rMimeType, rValue, aGraphic ))
{
rGrafObj.NbcSetGraphic( aGraphic );
rGrafObj.ActionChanged();
}
else if( SotExchange::GetFormatIdFromMimeType( rMimeType ) != sfx2::LinkManager::RegisterStatusInfoId() )
{
// broadcasting, to update slide sorter
rGrafObj.BroadcastObjectChange();
}
}
return SUCCESS;
}
void SdrGraphicLink::Closed()
{
// close connection; set pLink of the object to NULL, as link instance is just about getting destructed.
rGrafObj.ForceSwapIn();
rGrafObj.pGraphicLink=nullptr;
rGrafObj.ReleaseGraphicLink();
SvBaseLink::Closed();
}
void SdrGraphicLink::UpdateAsynchron()
{
if( GetObj() )
{
if ( pGraphicUpdater )
{
if ( pGraphicUpdater->GraphicLinkChanged( rGrafObj.GetFileName() ) )
{
pGraphicUpdater->Terminate();
pGraphicUpdater = new SdrGraphicUpdater( rGrafObj.GetFileName(), rGrafObj.GetFilterName(), *this );
}
}
else
pGraphicUpdater = new SdrGraphicUpdater( rGrafObj.GetFileName(), rGrafObj.GetFilterName(), *this );
}
}
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()
{
if (!pGraphic || pGraphic->IsSwappedOut()) // don't force swap-in for this
return;
const VectorGraphicDataPtr& rVectorGraphicDataPtr = pGraphic->GetGraphic().getVectorGraphicData();
if (!rVectorGraphicDataPtr.get())
return;
const drawinglayer::primitive2d::Primitive2DContainer aSequence(rVectorGraphicDataPtr->getPrimitive2DSequence());
if (aSequence.empty())
return;
drawinglayer::geometry::ViewInformation2D aViewInformation2D;
drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D aProcessor(aViewInformation2D);
aProcessor.process(aSequence);
const drawinglayer::primitive2d::ObjectInfoPrimitive2D* pResult = aProcessor.getResult();
if (!pResult)
return;
OUString aName = pResult->getName();
OUString aTitle = pResult->getTitle();
OUString aDesc = pResult->getDesc();
if(!aName.isEmpty())
{
SetName(aName);
}
if(!aTitle.isEmpty())
{
SetTitle(aTitle);
}
if(!aDesc.isEmpty())
{
SetDescription(aDesc);
}
}
SdrGrafObj::SdrGrafObj()
: SdrRectObj(),
pGraphicLink ( nullptr ),
bMirrored ( false )
{
pGraphic = new GraphicObject;
mpReplacementGraphic = nullptr;
pGraphic->SetSwapStreamHdl( LINK(this, SdrGrafObj, ImpSwapHdl) );
onGraphicChanged();
// #i118485# Shear allowed and possible now
bNoShear = false;
mbGrafAnimationAllowed = true;
// #i25616#
mbLineIsOutsideGeometry = true;
mbInsidePaint = false;
mbIsPreview = false;
// #i25616#
mbSupportTextIndentingOnLineWidthChange = false;
}
SdrGrafObj::SdrGrafObj(const Graphic& rGrf, const tools::Rectangle& rRect)
: SdrRectObj ( rRect ),
pGraphicLink ( nullptr ),
bMirrored ( false )
{
pGraphic = new GraphicObject( rGrf );
mpReplacementGraphic = nullptr;
pGraphic->SetSwapStreamHdl( LINK(this, SdrGrafObj, ImpSwapHdl) );
onGraphicChanged();
// #i118485# Shear allowed and possible now
bNoShear = false;
mbGrafAnimationAllowed = true;
// #i25616#
mbLineIsOutsideGeometry = true;
mbInsidePaint = false;
mbIsPreview = false;
// #i25616#
mbSupportTextIndentingOnLineWidthChange = false;
}
SdrGrafObj::SdrGrafObj( const Graphic& rGrf )
: SdrRectObj(),
pGraphicLink ( nullptr ),
bMirrored ( false )
{
pGraphic = new GraphicObject( rGrf );
mpReplacementGraphic = nullptr;
pGraphic->SetSwapStreamHdl( LINK(this, SdrGrafObj, ImpSwapHdl) );
onGraphicChanged();
// #i118485# Shear allowed and possible now
bNoShear = false;
mbGrafAnimationAllowed = true;
// #i25616#
mbLineIsOutsideGeometry = true;
mbInsidePaint = false;
mbIsPreview = false;
// #i25616#
mbSupportTextIndentingOnLineWidthChange = false;
}
SdrGrafObj::~SdrGrafObj()
{
delete pGraphic;
delete mpReplacementGraphic;
ImpDeregisterLink();
}
void SdrGrafObj::SetGraphicObject( const GraphicObject& rGrfObj )
{
*pGraphic = rGrfObj;
delete mpReplacementGraphic;
mpReplacementGraphic = nullptr;
pGraphic->SetSwapStreamHdl( LINK(this, SdrGrafObj, ImpSwapHdl) );
pGraphic->SetUserData();
mbIsPreview = 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 VectorGraphicDataPtr& rVectorGraphicDataPtr = pGraphic->GetGraphic().getVectorGraphicData();
if(rVectorGraphicDataPtr.get())
{
const_cast< SdrGrafObj* >(this)->mpReplacementGraphic = new GraphicObject(rVectorGraphicDataPtr->getReplacement());
}
else if (pGraphic->GetGraphic().getPdfData().hasElements())
{
// Replacement graphic for bitmap + PDF is just the bitmap.
const_cast<SdrGrafObj*>(this)->mpReplacementGraphic = new GraphicObject(pGraphic->GetGraphic().GetBitmapEx());
}
if (mpReplacementGraphic)
{
mpReplacementGraphic->SetSwapStreamHdl(
LINK(const_cast<SdrGrafObj*>(this), SdrGrafObj, ReplacementSwapHdl));
}
}
return mpReplacementGraphic;
}
void SdrGrafObj::NbcSetGraphic( const Graphic& rGrf )
{
pGraphic->SetGraphic( rGrf );
delete mpReplacementGraphic;
mpReplacementGraphic = nullptr;
pGraphic->SetUserData();
mbIsPreview = false;
onGraphicChanged();
}
void SdrGrafObj::SetGraphic( const Graphic& rGrf )
{
NbcSetGraphic(rGrf);
SetChanged();
BroadcastObjectChange();
}
const Graphic& SdrGrafObj::GetGraphic() const
{
ForceSwapIn();
return pGraphic->GetGraphic();
}
Graphic SdrGrafObj::GetTransformedGraphic( SdrGrafObjTransformsAttrs nTransformFlags ) const
{
// Refactored most of the code to GraphicObject, where
// everybody can use e.g. the cropping functionality
MapMode aDestMap( pModel->GetScaleUnit(), Point(), pModel->GetScaleFraction(), pModel->GetScaleFraction() );
const Size aDestSize( GetLogicRect().GetSize() );
GraphicAttr aActAttr = GetGraphicAttr(nTransformFlags);
// Delegate to moved code in GraphicObject
return GetGraphicObject().GetTransformedGraphic( aDestSize, aDestMap, aActAttr );
}
GraphicType SdrGrafObj::GetGraphicType() const
{
return pGraphic->GetType();
}
GraphicAttr SdrGrafObj::GetGraphicAttr( SdrGrafObjTransformsAttrs nTransformFlags ) const
{
GraphicAttr aActAttr;
GraphicType eType = GetGraphicType();
if( SdrGrafObjTransformsAttrs::NONE != nTransformFlags &&
GraphicType::NONE != eType )
{
const bool bMirror = bool( nTransformFlags & SdrGrafObjTransformsAttrs::MIRROR );
const bool bRotate = bool( nTransformFlags & SdrGrafObjTransformsAttrs::ROTATE ) &&
( aGeo.nRotationAngle && aGeo.nRotationAngle != 18000 ) && ( GraphicType::NONE != eType );
// Need cropping info earlier
const_cast<SdrGrafObj*>(this)->ImpSetAttrToGrafInfo();
// Actually transform the graphic only in this case.
// Cropping always happens, though.
aActAttr = aGrafInfo;
if( bMirror )
{
sal_uInt16 nMirrorCase = ( aGeo.nRotationAngle == 18000 ) ? ( bMirrored ? 3 : 4 ) : ( bMirrored ? 2 : 1 );
bool bHMirr = nMirrorCase == 2 || nMirrorCase == 4;
bool bVMirr = nMirrorCase == 3 || nMirrorCase == 4;
aActAttr.SetMirrorFlags( ( bHMirr ? BmpMirrorFlags::Horizontal : BmpMirrorFlags::NONE ) | ( bVMirr ? BmpMirrorFlags::Vertical : BmpMirrorFlags::NONE ) );
}
if( bRotate )
aActAttr.SetRotation( sal_uInt16(aGeo.nRotationAngle / 10) );
}
return aActAttr;
}
bool SdrGrafObj::IsAnimated() const
{
return pGraphic->IsAnimated();
}
bool SdrGrafObj::IsEPS() const
{
return pGraphic->IsEPS();
}
bool SdrGrafObj::IsSwappedOut() const
{
return mbIsPreview || pGraphic->IsSwappedOut();
}
const MapMode& SdrGrafObj::GetGrafPrefMapMode() const
{
return pGraphic->GetPrefMapMode();
}
const Size& SdrGrafObj::GetGrafPrefSize() const
{
return pGraphic->GetPrefSize();
}
void SdrGrafObj::SetGrafStreamURL( const OUString& rGraphicStreamURL )
{
mbIsPreview = false;
if( rGraphicStreamURL.isEmpty() )
{
pGraphic->SetUserData();
}
else if( pModel->IsSwapGraphics() )
{
pGraphic->SetUserData( rGraphicStreamURL );
}
}
OUString SdrGrafObj::GetGrafStreamURL() const
{
return pGraphic->GetUserData();
}
Size SdrGrafObj::getOriginalSize() const
{
Size aSize = GetGrafPrefSize();
if (aGrafInfo.IsCropped())
{
long aCroppedTop = OutputDevice::LogicToLogic( aGrafInfo.GetTopCrop(), GetModel()->GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit());
long aCroppedBottom = OutputDevice::LogicToLogic( aGrafInfo.GetBottomCrop(), GetModel()->GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit());
long aCroppedLeft = OutputDevice::LogicToLogic( aGrafInfo.GetLeftCrop(), GetModel()->GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit());
long aCroppedRight = OutputDevice::LogicToLogic( aGrafInfo.GetRightCrop(), GetModel()->GetScaleUnit(), GetGrafPrefMapMode().GetMapUnit());
long aCroppedWidth = aSize.getWidth() - aCroppedLeft + aCroppedRight;
long aCroppedHeight = aSize.getHeight() - aCroppedTop + aCroppedBottom;
aSize = Size ( aCroppedWidth, aCroppedHeight);
}
if ( GetGrafPrefMapMode().GetMapUnit() == MapUnit::MapPixel )
aSize = Application::GetDefaultDevice()->PixelToLogic( aSize, GetModel()->GetScaleUnit() );
else
aSize = OutputDevice::LogicToLogic( aSize, GetGrafPrefMapMode(), GetModel()->GetScaleUnit() );
return aSize;
}
void SdrGrafObj::ForceSwapIn() const
{
if( mbIsPreview && pGraphic->HasUserData() )
{
// removing preview graphic
const OUString aUserData( pGraphic->GetUserData() );
Graphic aEmpty;
pGraphic->SetGraphic( aEmpty );
pGraphic->SetUserData( aUserData );
const_cast< SdrGrafObj* >( this )->mbIsPreview = false;
}
if ( pGraphicLink && pGraphic->IsSwappedOut() )
ImpUpdateGraphicLink( false );
else
pGraphic->FireSwapInRequest();
if( pGraphic->IsSwappedOut() ||
( pGraphic->GetType() == GraphicType::NONE ) ||
( pGraphic->GetType() == GraphicType::Default ) )
{
Graphic aDefaultGraphic;
aDefaultGraphic.SetDefaultType();
pGraphic->SetGraphic( aDefaultGraphic );
}
}
void SdrGrafObj::ImpRegisterLink()
{
sfx2::LinkManager* pLinkManager = pModel != nullptr ? pModel->GetLinkManager() : nullptr;
if( pLinkManager != nullptr && pGraphicLink == nullptr )
{
if (!aFileName.isEmpty())
{
pGraphicLink = new SdrGraphicLink( *this );
pLinkManager->InsertFileLink(
*pGraphicLink, OBJECT_CLIENT_GRF, aFileName, (aFilterName.isEmpty() ? nullptr : &aFilterName));
pGraphicLink->Connect();
}
}
}
void SdrGrafObj::ImpDeregisterLink()
{
sfx2::LinkManager* pLinkManager = pModel != nullptr ? pModel->GetLinkManager() : nullptr;
if( pLinkManager != nullptr && pGraphicLink!=nullptr)
{
// When using Remove, the *pGraphicLink is implicitly deleted
pLinkManager->Remove( pGraphicLink );
pGraphicLink=nullptr;
}
}
void SdrGrafObj::SetGraphicLink(const OUString& rFileName, const OUString& rReferer, const OUString& rFilterName)
{
ImpDeregisterLink();
aFileName = rFileName;
aReferer = rReferer;
aFilterName = rFilterName;
ImpRegisterLink();
pGraphic->SetUserData();
pGraphic->SetSwapState();
}
void SdrGrafObj::ReleaseGraphicLink()
{
ImpDeregisterLink();
aFileName.clear();
aReferer.clear();
aFilterName.clear();
}
bool SdrGrafObj::IsLinkedGraphic() const
{
return !aFileName.isEmpty();
}
void SdrGrafObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
{
bool bNoPresGrf = ( pGraphic->GetType() != GraphicType::NONE ) && !bEmptyPresObj;
rInfo.bResizeFreeAllowed = aGeo.nRotationAngle % 9000 == 0 ||
aGeo.nRotationAngle % 18000 == 0 ||
aGeo.nRotationAngle % 27000 == 0;
rInfo.bResizePropAllowed = true;
rInfo.bRotateFreeAllowed = bNoPresGrf;
rInfo.bRotate90Allowed = bNoPresGrf;
rInfo.bMirrorFreeAllowed = bNoPresGrf;
rInfo.bMirror45Allowed = bNoPresGrf;
rInfo.bMirror90Allowed = !bEmptyPresObj;
rInfo.bTransparenceAllowed = false;
// #i118485# Shear allowed and possible now
rInfo.bShearAllowed = true;
rInfo.bEdgeRadiusAllowed=false;
rInfo.bCanConvToPath = !IsEPS();
rInfo.bCanConvToPathLineToArea = false;
rInfo.bCanConvToPolyLineToArea = 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
*/
bool SdrGrafObj::ImpUpdateGraphicLink( bool bAsynchron ) const
{
bool bRet = false;
if( pGraphicLink )
{
if ( bAsynchron )
pGraphicLink->UpdateAsynchron();
else
pGraphicLink->DataChanged( ImpLoadLinkedGraphic( aFileName, aReferer, aFilterName ) );
bRet = true;
}
return bRet;
}
void SdrGrafObj::ImpSetLinkedGraphic( const Graphic& rGraphic )
{
const bool bIsChanged = GetModel()->IsChanged();
NbcSetGraphic( rGraphic );
ActionChanged();
BroadcastObjectChange();
GetModel()->SetChanged( bIsChanged );
}
OUString SdrGrafObj::TakeObjNameSingul() const
{
if (!pGraphic)
return OUString();
const VectorGraphicDataPtr& rVectorGraphicDataPtr = pGraphic->GetGraphic().getVectorGraphicData();
OUStringBuffer sName;
if(rVectorGraphicDataPtr.get())
{
switch (rVectorGraphicDataPtr->getVectorGraphicDataType())
{
case VectorGraphicDataType::Wmf:
{
sName.append(ImpGetResStr(STR_ObjNameSingulGRAFWMF));
break;
}
case VectorGraphicDataType::Emf:
{
sName.append(ImpGetResStr(STR_ObjNameSingulGRAFEMF));
break;
}
default: // case VectorGraphicDataType::Svg:
{
sName.append(ImpGetResStr(STR_ObjNameSingulGRAFSVG));
break;
}
}
}
else
{
switch( pGraphic->GetType() )
{
case GraphicType::Bitmap:
{
const char* pId = ( ( pGraphic->IsTransparent() || static_cast<const SdrGrafTransparenceItem&>( GetObjectItem( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() ) ?
( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPTRANSLNK : STR_ObjNameSingulGRAFBMPTRANS ) :
( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPLNK : STR_ObjNameSingulGRAFBMP ) );
sName.append(ImpGetResStr(pId));
}
break;
case GraphicType::GdiMetafile:
sName.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNK : STR_ObjNameSingulGRAFMTF));
break;
case GraphicType::NONE:
sName.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNK : STR_ObjNameSingulGRAFNONE));
break;
default:
sName.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNK : STR_ObjNameSingulGRAF));
break;
}
}
const OUString aName(GetName());
if (!aName.isEmpty())
{
sName.append(" '");
sName.append(aName);
sName.append('\'' );
}
return sName.makeStringAndClear();
}
OUString SdrGrafObj::TakeObjNamePlural() const
{
if(!pGraphic)
return OUString();
const VectorGraphicDataPtr& rVectorGraphicDataPtr = pGraphic->GetGraphic().getVectorGraphicData();
OUStringBuffer sName;
if(rVectorGraphicDataPtr.get())
{
switch (rVectorGraphicDataPtr->getVectorGraphicDataType())
{
case VectorGraphicDataType::Wmf:
{
sName.append(ImpGetResStr(STR_ObjNamePluralGRAFWMF));
break;
}
case VectorGraphicDataType::Emf:
{
sName.append(ImpGetResStr(STR_ObjNamePluralGRAFEMF));
break;
}
default: // case VectorGraphicDataType::Svg:
{
sName.append(ImpGetResStr(STR_ObjNamePluralGRAFSVG));
break;
}
}
}
else
{
switch( pGraphic->GetType() )
{
case GraphicType::Bitmap:
{
const char* pId = ( ( pGraphic->IsTransparent() || static_cast<const SdrGrafTransparenceItem&>( GetObjectItem( SDRATTR_GRAFTRANSPARENCE ) ).GetValue() ) ?
( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPTRANSLNK : STR_ObjNamePluralGRAFBMPTRANS ) :
( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPLNK : STR_ObjNamePluralGRAFBMP ) );
sName.append(ImpGetResStr(pId));
}
break;
case GraphicType::GdiMetafile:
sName.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNK : STR_ObjNamePluralGRAFMTF));
break;
case GraphicType::NONE:
sName.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNK : STR_ObjNamePluralGRAFNONE));
break;
default:
sName.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNK : STR_ObjNamePluralGRAF));
break;
}
}
const OUString aName(GetName());
if (!aName.isEmpty())
{
sName.append(" '");
sName.append(aName);
sName.append('\'');
}
return sName.makeStringAndClear();
}
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;
}
SdrGrafObj* SdrGrafObj::Clone() const
{
return CloneHelper< SdrGrafObj >();
}
SdrGrafObj& SdrGrafObj::operator=( const SdrGrafObj& rObj )
{
if( this == &rObj )
return *this;
SdrRectObj::operator=( rObj );
pGraphic->SetGraphic( rObj.GetGraphic(), &rObj.GetGraphicObject() );
aFileName = rObj.aFileName;
aFilterName = rObj.aFilterName;
bMirrored = rObj.bMirrored;
if( rObj.IsLinkedGraphic() )
{
SetGraphicLink( aFileName, rObj.aReferer, aFilterName );
}
ImpSetAttrToGrafInfo();
return *this;
}
basegfx::B2DPolyPolygon SdrGrafObj::TakeXorPoly() const
{
if(mbInsidePaint)
{
basegfx::B2DPolyPolygon aRetval;
// take grown rectangle
const sal_Int32 nHalfLineWidth(ImpGetLineWdt() / 2);
const tools::Rectangle aGrownRect(
maRect.Left() - nHalfLineWidth,
maRect.Top() - nHalfLineWidth,
maRect.Right() + nHalfLineWidth,
maRect.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 + 1 );
}
void SdrGrafObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
{
SdrRectObj::NbcResize( rRef, xFact, yFact );
bool bMirrX = xFact.GetNumerator() < 0;
bool bMirrY = yFact.GetNumerator() < 0;
if( bMirrX != bMirrY )
bMirrored = !bMirrored;
}
void SdrGrafObj::NbcMirror(const Point& rRef1, const Point& rRef2)
{
SdrRectObj::NbcMirror(rRef1,rRef2);
bMirrored = !bMirrored;
}
SdrObjGeoData* SdrGrafObj::NewGeoData() const
{
return new SdrGrafObjGeoData;
}
void SdrGrafObj::SaveGeoData(SdrObjGeoData& rGeo) const
{
SdrRectObj::SaveGeoData(rGeo);
SdrGrafObjGeoData& rGGeo=static_cast<SdrGrafObjGeoData&>(rGeo);
rGGeo.bMirrored=bMirrored;
}
void SdrGrafObj::RestGeoData(const SdrObjGeoData& rGeo)
{
SdrRectObj::RestGeoData(rGeo);
const SdrGrafObjGeoData& rGGeo=static_cast<const SdrGrafObjGeoData&>(rGeo);
bMirrored=rGGeo.bMirrored;
}
void SdrGrafObj::SetPage( SdrPage* pNewPage )
{
bool bRemove = pNewPage == nullptr && pPage != nullptr;
bool bInsert = pNewPage != nullptr && pPage == nullptr;
if( bRemove )
{
// No SwapIn necessary here, because if something's not loaded, it can't be animated either.
if( pGraphic->IsAnimated())
pGraphic->StopAnimation();
if( pGraphicLink != nullptr )
ImpDeregisterLink();
}
if(!pModel && !GetStyleSheet() && pNewPage && pNewPage->GetModel())
{
// #i119287# 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(drawing::FillStyle_NONE));
SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
}
}
SdrRectObj::SetPage( pNewPage );
if (!aFileName.isEmpty() && bInsert)
ImpRegisterLink();
}
void SdrGrafObj::SetModel( SdrModel* pNewModel )
{
bool bChg = pNewModel != pModel;
if( bChg )
{
if( pGraphic->HasUserData() )
{
ForceSwapIn();
}
if( pGraphicLink != nullptr )
ImpDeregisterLink();
}
// realize model
SdrRectObj::SetModel(pNewModel);
if (bChg && !aFileName.isEmpty())
ImpRegisterLink();
}
void SdrGrafObj::StartAnimation()
{
SetGrafAnimationAllowed(true);
}
bool SdrGrafObj::HasGDIMetaFile() const
{
return( pGraphic->GetType() == GraphicType::GdiMetafile );
}
bool SdrGrafObj::isEmbeddedVectorGraphicData() const
{
return GraphicType::Bitmap == GetGraphicType() && GetGraphic().getVectorGraphicData().get();
}
GDIMetaFile SdrGrafObj::getMetafileFromEmbeddedVectorGraphicData() const
{
GDIMetaFile aRetval;
if(isEmbeddedVectorGraphicData() && GetModel())
{
ScopedVclPtrInstance< VirtualDevice > pOut;
const tools::Rectangle aBoundRect(GetCurrentBoundRect());
const MapMode aMap(GetModel()->GetScaleUnit(), Point(), GetModel()->GetScaleFraction(), GetModel()->GetScaleFraction());
pOut->EnableOutput(false);
pOut->SetMapMode(aMap);
aRetval.Record(pOut);
SingleObjectPainter(*pOut.get());
aRetval.Stop();
aRetval.WindStart();
aRetval.Move(-aBoundRect.Left(), -aBoundRect.Top());
aRetval.SetPrefMapMode(aMap);
aRetval.SetPrefSize(aBoundRect.GetSize());
}
return aRetval;
}
GDIMetaFile SdrGrafObj::GetMetaFile(GraphicType &rGraphicType) const
{
if (isEmbeddedVectorGraphicData())
{
// Embedded Vector Graphic Data
// 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
rGraphicType = GraphicType::GdiMetafile;
return getMetafileFromEmbeddedVectorGraphicData();
}
else if (GraphicType::GdiMetafile == rGraphicType)
{
return GetTransformedGraphic(SdrGrafObjTransformsAttrs::COLOR|SdrGrafObjTransformsAttrs::MIRROR).GetGDIMetaFile();
}
return GDIMetaFile();
}
SdrObject* SdrGrafObj::DoConvertToPolyObj(bool bBezier, bool bAddText ) const
{
SdrObject* pRetval = nullptr;
GraphicType aGraphicType(GetGraphicType());
GDIMetaFile aMtf(GetMetaFile(aGraphicType));
switch(aGraphicType)
{
case GraphicType::GdiMetafile:
{
// Sort into group and return ONLY those objects that can be created from the MetaFile.
ImpSdrGDIMetaFileImport aFilter(*GetModel(), GetLayer(), maRect);
SdrObjGroup* pGrp = new SdrObjGroup();
if(aFilter.DoImport(aMtf, *pGrp->GetSubList(), 0))
{
{
// copy transformation
GeoStat aGeoStat(GetGeoStat());
if(aGeoStat.nShearAngle)
{
aGeoStat.RecalcTan();
pGrp->NbcShear(maRect.TopLeft(), aGeoStat.nShearAngle, aGeoStat.nTan, false);
}
if(aGeoStat.nRotationAngle)
{
aGeoStat.RecalcSinCos();
pGrp->NbcRotate(maRect.TopLeft(), aGeoStat.nRotationAngle, 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 GraphicType::Bitmap:
{
// create basic object and add fill
pRetval = SdrRectObj::DoConvertToPolyObj(bBezier, bAddText);
// save bitmap as an attribute
if(pRetval)
{
// retrieve bitmap for the fill
SfxItemSet aSet(GetObjectItemSet());
aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP));
const BitmapEx aBitmapEx(GetTransformedGraphic().GetBitmapEx());
aSet.Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx)));
aSet.Put(XFillBmpTileItem(false));
pRetval->SetMergedItemSet(aSet);
}
break;
}
case GraphicType::NONE:
case GraphicType::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::SetMirrored( bool _bMirrored )
{
bMirrored = _bMirrored;
}
void SdrGrafObj::ImpSetAttrToGrafInfo()
{
const SfxItemSet& rSet = GetObjectItemSet();
const sal_uInt16 nTrans = static_cast<const SdrGrafTransparenceItem&>( rSet.Get( SDRATTR_GRAFTRANSPARENCE ) ).GetValue();
const SdrGrafCropItem& rCrop = static_cast<const SdrGrafCropItem&>( rSet.Get( SDRATTR_GRAFCROP ) );
aGrafInfo.SetLuminance( static_cast<const SdrGrafLuminanceItem&>( rSet.Get( SDRATTR_GRAFLUMINANCE ) ).GetValue() );
aGrafInfo.SetContrast( static_cast<const SdrGrafContrastItem&>( rSet.Get( SDRATTR_GRAFCONTRAST ) ).GetValue() );
aGrafInfo.SetChannelR( static_cast<const SdrGrafRedItem&>( rSet.Get( SDRATTR_GRAFRED ) ).GetValue() );
aGrafInfo.SetChannelG( static_cast<const SdrGrafGreenItem&>( rSet.Get( SDRATTR_GRAFGREEN ) ).GetValue() );
aGrafInfo.SetChannelB( static_cast<const SdrGrafBlueItem&>( rSet.Get( SDRATTR_GRAFBLUE ) ).GetValue() );
aGrafInfo.SetGamma( static_cast<const SdrGrafGamma100Item&>( rSet.Get( SDRATTR_GRAFGAMMA ) ).GetValue() * 0.01 );
aGrafInfo.SetTransparency( (sal_uInt8) FRound( std::min( nTrans, (sal_uInt16) 100 ) * 2.55 ) );
aGrafInfo.SetInvert( static_cast<const SdrGrafInvertItem&>( rSet.Get( SDRATTR_GRAFINVERT ) ).GetValue() );
aGrafInfo.SetDrawMode( static_cast<const SdrGrafModeItem&>( rSet.Get( SDRATTR_GRAFMODE ) ).GetValue() );
aGrafInfo.SetCrop( rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom() );
SetXPolyDirty();
SetRectsDirty();
}
void SdrGrafObj::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly )
{
Size aSize;
Size aMaxSize( rMaxRect.GetSize() );
if ( pGraphic->GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel )
aSize = Application::GetDefaultDevice()->PixelToLogic( pGraphic->GetPrefSize(), MapUnit::Map100thMM );
else
aSize = OutputDevice::LogicToLogic( pGraphic->GetPrefSize(),
pGraphic->GetPrefMapMode(),
MapMode( MapUnit::Map100thMM ) );
if( aSize.Height() != 0 && aSize.Width() != 0 )
{
Point aPos( rMaxRect.TopLeft() );
// if the graphic is too large, fit it to page
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();
// Scale graphic to page size
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 = maRect.TopLeft();
aPos.X() -= aSize.Width() / 2;
aPos.Y() -= aSize.Height() / 2;
SetLogicRect( tools::Rectangle( aPos, aSize ) );
}
}
IMPL_LINK(SdrGrafObj, ReplacementSwapHdl, const GraphicObject*, pO, SvStream*)
{
// replacement image is always swapped
if (pO->IsInSwapOut())
{
SdrSwapGraphicsMode const nSwapMode(pModel->GetSwapGraphicsMode());
if (nSwapMode & SdrSwapGraphicsMode::TEMP)
{
return GRFMGR_AUTOSWAPSTREAM_TEMP;
}
}
else if (pO->IsInSwapIn())
{
return GRFMGR_AUTOSWAPSTREAM_TEMP;
}
else
{
assert(!"why is swap handler being called?");
}
return GRFMGR_AUTOSWAPSTREAM_NONE;
}
IMPL_LINK( SdrGrafObj, ImpSwapHdl, const GraphicObject*, pO, SvStream* )
{
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())
{
const SdrSwapGraphicsMode nSwapMode = pModel->GetSwapGraphicsMode();
if( ( pGraphicLink ) &&
( nSwapMode & SdrSwapGraphicsMode::PURGE ) )
{
pRet = GRFMGR_AUTOSWAPSTREAM_LINK;
}
else if( nSwapMode & SdrSwapGraphicsMode::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() )
{
// can be loaded from the original document stream later
if( pModel != nullptr )
{
if( pGraphic->HasUserData() )
{
::comphelper::LifecycleProxy proxy;
OUString aUserData = pGraphic->GetUserData();
uno::Reference<io::XInputStream> const xStream(
pModel->GetDocumentStream(aUserData, proxy));
std::unique_ptr<SvStream> const pStream( (xStream.is())
? ::utl::UcbStreamHelper::CreateStream(xStream)
: nullptr );
if( pStream != nullptr )
{
Graphic aGraphic;
std::unique_ptr<css::uno::Sequence< css::beans::PropertyValue > > pFilterData;
if(mbInsidePaint && !GetViewContact().HasViewObjectContacts())
{
pFilterData.reset(new css::uno::Sequence< css::beans::PropertyValue >( 3 ));
const css::awt::Size aPreviewSizeHint( 64, 64 );
const bool bAllowPartialStreamRead = 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 bool bCreateNativeLink = true;
(*pFilterData)[ 0 ].Name = "PreviewSizeHint";
(*pFilterData)[ 0 ].Value <<= aPreviewSizeHint;
(*pFilterData)[ 1 ].Name = "AllowPartialStreamRead";
(*pFilterData)[ 1 ].Value <<= bAllowPartialStreamRead;
(*pFilterData)[ 2 ].Name = "CreateNativeLink";
(*pFilterData)[ 2 ].Value <<= bCreateNativeLink;
mbIsPreview = true;
}
if(!GraphicFilter::GetGraphicFilter().ImportGraphic(
aGraphic, aUserData, *pStream,
GRFILTER_FORMAT_DONTKNOW, nullptr, GraphicFilterImportFlags::NONE, pFilterData.get()))
{
const OUString aNewUserData( pGraphic->GetUserData() );
pGraphic->SetGraphic( aGraphic );
if( mbIsPreview )
{
pGraphic->SetUserData(aNewUserData);
}
else
{
pGraphic->SetUserData();
}
// Graphic successfully swapped in.
pRet = GRFMGR_AUTOSWAPSTREAM_LOADED;
}
pFilterData.reset();
pStream->ResetError();
}
}
else if( !ImpUpdateGraphicLink( false ) )
{
pRet = GRFMGR_AUTOSWAPSTREAM_TEMP;
}
else
{
pRet = GRFMGR_AUTOSWAPSTREAM_LOADED;
}
}
else
pRet = GRFMGR_AUTOSWAPSTREAM_TEMP;
}
return pRet;
}
void SdrGrafObj::SetGrafAnimationAllowed(bool bNew)
{
if(mbGrafAnimationAllowed != bNew)
{
mbGrafAnimationAllowed = bNew;
ActionChanged();
}
}
Reference< XInputStream > SdrGrafObj::getInputStream()
{
Reference< XInputStream > xStream;
if( pModel )
{
if( pGraphic && GetGraphic().IsLink() )
{
Graphic aGraphic( GetGraphic() );
GfxLink aLink( aGraphic.GetLink() );
sal_uInt32 nSize = aLink.GetDataSize();
const void* pSourceData = static_cast<const void*>(aLink.GetData());
if( nSize && pSourceData )
{
sal_uInt8 * pBuffer = new sal_uInt8[ nSize ];
memcpy( pBuffer, pSourceData, nSize );
SvMemoryStream* pStream = new SvMemoryStream( static_cast<void*>(pBuffer), (std::size_t)nSize, StreamMode::READ );
pStream->ObjectOwnsMemory( true );
xStream.set( new utl::OInputStreamWrapper( pStream, true ) );
}
}
if (!xStream.is() && !aFileName.isEmpty())
{
SvFileStream* pStream = new SvFileStream( aFileName, StreamMode::READ );
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::utils::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 fLclRotate, fLclShearX;
aMatrix.decompose(aScale, aTranslate, fLclRotate, fLclShearX);
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())), SdrHdlKind::UpperLeft, fShearX, fRotate));
aPos = aMatrix * basegfx::B2DPoint(0.5, 0.0);
rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Upper, fShearX, fRotate));
aPos = aMatrix * basegfx::B2DPoint(1.0, 0.0);
rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::UpperRight, fShearX, fRotate));
aPos = aMatrix * basegfx::B2DPoint(0.0, 0.5);
rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Left , fShearX, fRotate));
aPos = aMatrix * basegfx::B2DPoint(1.0, 0.5);
rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Right, fShearX, fRotate));
aPos = aMatrix * basegfx::B2DPoint(0.0, 1.0);
rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerLeft, fShearX, fRotate));
aPos = aMatrix * basegfx::B2DPoint(0.5, 1.0);
rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Lower, fShearX, fRotate));
aPos = aMatrix * basegfx::B2DPoint(1.0, 1.0);
rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerRight, fShearX, fRotate));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */