1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <unotools/streamwrap.hxx>
22 #include <sfx2/lnkbase.hxx>
24 #include <tools/helpers.hxx>
25 #include <sot/formats.hxx>
26 #include <sot/storage.hxx>
27 #include <comphelper/storagehelper.hxx>
28 #include <unotools/ucbstreamhelper.hxx>
29 #include <unotools/localfilehelper.hxx>
30 #include <svl/style.hxx>
31 #include <vcl/graphicfilter.hxx>
32 #include <svl/urihelper.hxx>
33 #include <svtools/grfmgr.hxx>
34 #include <vcl/svapp.hxx>
36 #include <sfx2/linkmgr.hxx>
37 #include <sfx2/docfile.hxx>
38 #include <svx/svdetc.hxx>
39 #include "svdglob.hxx"
40 #include "svx/svdstr.hrc"
41 #include <svx/svdpool.hxx>
42 #include <svx/svdmodel.hxx>
43 #include <svx/svdpage.hxx>
44 #include <svx/svdmrkv.hxx>
45 #include <svx/svdpagv.hxx>
46 #include "svx/svdviter.hxx"
47 #include <svx/svdview.hxx>
48 #include <svx/svdograf.hxx>
49 #include <svx/svdogrp.hxx>
50 #include <svx/xbtmpit.hxx>
51 #include <svx/xflbmtit.hxx>
52 #include <svx/svdundo.hxx>
53 #include "svdfmtf.hxx"
54 #include <svx/sdgcpitm.hxx>
55 #include <editeng/eeitem.hxx>
56 #include <sdr/properties/graphicproperties.hxx>
57 #include <sdr/contact/viewcontactofgraphic.hxx>
58 #include <basegfx/matrix/b2dhommatrixtools.hxx>
59 #include <basegfx/polygon/b2dpolygon.hxx>
60 #include <basegfx/polygon/b2dpolygontools.hxx>
61 #include <osl/thread.hxx>
62 #include <drawinglayer/processor2d/objectinfoextractor2d.hxx>
63 #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
64 #include <boost/scoped_ptr.hpp>
66 using namespace ::com::sun::star
;
67 using namespace ::com::sun::star::uno
;
68 using namespace ::com::sun::star::io
;
70 const Graphic
ImpLoadLinkedGraphic( const OUString
& aFileName
, const OUString
& aReferer
, const OUString
& aFilterName
)
74 SfxMedium
xMed( aFileName
, aReferer
, STREAM_STD_READ
);
77 SvStream
* pInStrm
= xMed
.GetInStream();
80 pInStrm
->Seek( STREAM_SEEK_TO_BEGIN
);
81 GraphicFilter
& rGF
= GraphicFilter::GetGraphicFilter();
83 const sal_uInt16 nFilter
= !aFilterName
.isEmpty() && rGF
.GetImportFormatCount()
84 ? rGF
.GetImportFormatNumber( aFilterName
)
85 : GRFILTER_FORMAT_DONTKNOW
;
87 css::uno::Sequence
< css::beans::PropertyValue
> aFilterData( 1 );
89 // TODO: Room for improvement:
90 // As this is a linked graphic the GfxLink is not needed if saving/loading our own format.
91 // But this link is required by some filters to access the native graphic (PDF export/MS export),
92 // there we should create a new service to provide this data if needed
93 aFilterData
[ 0 ].Name
= "CreateNativeLink";
94 aFilterData
[ 0 ].Value
= Any( sal_True
);
96 // #i123042# for e.g SVG the path is needed, so hand it over here. I have no real idea
97 // what consequences this may have; maybe this is not handed over by purpose here. Not
98 // handing it over means that any GraphicFormat that internallv needs a path as base
99 // to interpret included links may fail.
100 // Alternatively the path may be set at the result after this call when it is known
101 // that it is a SVG graphic, but only because no one yet tried to interpret it.
102 rGF
.ImportGraphic( aGraphic
, aFileName
, *pInStrm
, nFilter
, NULL
, GraphicFilterImportFlags::NONE
, &aFilterData
);
107 class SdrGraphicUpdater
;
108 class SdrGraphicLink
: public sfx2::SvBaseLink
110 SdrGrafObj
& rGrafObj
;
111 SdrGraphicUpdater
* pGraphicUpdater
;
114 SdrGraphicLink(SdrGrafObj
& rObj
);
115 virtual ~SdrGraphicLink();
117 virtual void Closed() SAL_OVERRIDE
;
119 virtual ::sfx2::SvBaseLink::UpdateResult
DataChanged(
120 const OUString
& rMimeType
, const ::com::sun::star::uno::Any
& rValue
) SAL_OVERRIDE
;
121 void DataChanged( const Graphic
& rGraphic
);
123 bool Connect() { return 0 != GetRealObject(); }
124 void UpdateAsynchron();
125 void RemoveGraphicUpdater();
127 OUString
getReferer() const { return rGrafObj
.aReferer
; }
130 class SdrGraphicUpdater
: public ::osl::Thread
133 SdrGraphicUpdater( const OUString
& rFileName
, const OUString
& rFilterName
, SdrGraphicLink
& );
134 virtual ~SdrGraphicUpdater();
136 void SAL_CALL
Terminate();
138 bool GraphicLinkChanged( const OUString
& rFileName
){ return maFileName
!= rFileName
; };
142 /** is called from the inherited create method and acts as the
143 main function of this thread.
145 virtual void SAL_CALL
run() SAL_OVERRIDE
;
147 /** Called after the thread is terminated via the terminate
148 method. Used to kill the thread by calling delete on this.
150 virtual void SAL_CALL
onTerminated() SAL_OVERRIDE
;
154 const OUString maFileName
;
155 const OUString maFilterName
;
156 SdrGraphicLink
& mrGraphicLink
;
158 volatile bool mbIsTerminated
;
161 SdrGraphicUpdater::SdrGraphicUpdater( const OUString
& rFileName
, const OUString
& rFilterName
, SdrGraphicLink
& rGraphicLink
)
162 : maFileName( rFileName
)
163 , maFilterName( rFilterName
)
164 , mrGraphicLink( rGraphicLink
)
165 , mbIsTerminated( false )
170 SdrGraphicUpdater::~SdrGraphicUpdater()
174 void SdrGraphicUpdater::Terminate()
176 mbIsTerminated
= true;
179 void SAL_CALL
SdrGraphicUpdater::onTerminated()
184 void SAL_CALL
SdrGraphicUpdater::run()
186 osl_setThreadName("SdrGraphicUpdater");
188 Graphic
aGraphic( ImpLoadLinkedGraphic( maFileName
, mrGraphicLink
.getReferer(), maFilterName
) );
189 SolarMutexGuard aSolarGuard
;
190 if ( !mbIsTerminated
)
192 mrGraphicLink
.DataChanged( aGraphic
);
193 mrGraphicLink
.RemoveGraphicUpdater();
197 SdrGraphicLink::SdrGraphicLink(SdrGrafObj
& rObj
)
198 : ::sfx2::SvBaseLink( ::SfxLinkUpdateMode::ONCALL
, SotClipboardFormatId::SVXB
)
200 , pGraphicUpdater( NULL
)
202 SetSynchron( false );
205 SdrGraphicLink::~SdrGraphicLink()
207 if ( pGraphicUpdater
)
208 pGraphicUpdater
->Terminate();
211 void SdrGraphicLink::DataChanged( const Graphic
& rGraphic
)
213 rGrafObj
.ImpSetLinkedGraphic( rGraphic
);
216 void SdrGraphicLink::RemoveGraphicUpdater()
218 pGraphicUpdater
= NULL
;
221 ::sfx2::SvBaseLink::UpdateResult
SdrGraphicLink::DataChanged(
222 const OUString
& rMimeType
, const ::com::sun::star::uno::Any
& rValue
)
224 SdrModel
* pModel
= rGrafObj
.GetModel();
225 sfx2::LinkManager
* pLinkManager
= pModel
? pModel
->GetLinkManager() : 0;
227 if( pLinkManager
&& rValue
.hasValue() )
229 sfx2::LinkManager::GetDisplayNames( this, 0, &rGrafObj
.aFileName
, 0, &rGrafObj
.aFilterName
);
232 if( sfx2::LinkManager::GetGraphicFromAny( rMimeType
, rValue
, aGraphic
))
234 rGrafObj
.NbcSetGraphic( aGraphic
);
235 rGrafObj
.ActionChanged();
237 else if( SotExchange::GetFormatIdFromMimeType( rMimeType
) != sfx2::LinkManager::RegisterStatusInfoId() )
239 // broadcasting, to update slide sorter
240 rGrafObj
.BroadcastObjectChange();
246 void SdrGraphicLink::Closed()
248 // close connection; set pLink of the object to NULL, as link instance is just about getting destructed.
249 rGrafObj
.ForceSwapIn();
250 rGrafObj
.pGraphicLink
=NULL
;
251 rGrafObj
.ReleaseGraphicLink();
252 SvBaseLink::Closed();
255 void SdrGraphicLink::UpdateAsynchron()
259 if ( pGraphicUpdater
)
261 if ( pGraphicUpdater
->GraphicLinkChanged( rGrafObj
.GetFileName() ) )
263 pGraphicUpdater
->Terminate();
264 pGraphicUpdater
= new SdrGraphicUpdater( rGrafObj
.GetFileName(), rGrafObj
.GetFilterName(), *this );
268 pGraphicUpdater
= new SdrGraphicUpdater( rGrafObj
.GetFileName(), rGrafObj
.GetFilterName(), *this );
272 sdr::properties::BaseProperties
* SdrGrafObj::CreateObjectSpecificProperties()
274 return new sdr::properties::GraphicProperties(*this);
278 // DrawContact section
280 sdr::contact::ViewContact
* SdrGrafObj::CreateObjectSpecificViewContact()
282 return new sdr::contact::ViewContactOfGraphic(*this);
286 // check if SVG and if try to get ObjectInfoPrimitive2D and extract info
288 void SdrGrafObj::onGraphicChanged()
290 if (!pGraphic
|| pGraphic
->IsSwappedOut()) // don't force swap-in for this
293 const SvgDataPtr
& rSvgDataPtr
= pGraphic
->GetGraphic().getSvgData();
295 if (!rSvgDataPtr
.get())
298 const drawinglayer::primitive2d::Primitive2DSequence
aSequence(rSvgDataPtr
->getPrimitive2DSequence());
300 if (!aSequence
.hasElements())
303 drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
304 drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D
aProcessor(aViewInformation2D
);
306 aProcessor
.process(aSequence
);
308 const drawinglayer::primitive2d::ObjectInfoPrimitive2D
* pResult
= aProcessor
.getResult();
313 OUString aName
= pResult
->getName();
314 OUString aTitle
= pResult
->getTitle();
315 OUString aDesc
= pResult
->getDesc();
322 if(!aTitle
.isEmpty())
329 SetDescription(aDesc
);
333 TYPEINIT1(SdrGrafObj
,SdrRectObj
);
335 SdrGrafObj::SdrGrafObj()
337 pGraphicLink ( NULL
),
340 pGraphic
= new GraphicObject
;
341 mpReplacementGraphic
= 0;
342 pGraphic
->SetSwapStreamHdl( LINK(this, SdrGrafObj
, ImpSwapHdl
) );
345 // #i118485# Shear allowed and possible now
348 mbGrafAnimationAllowed
= true;
351 mbLineIsOutsideGeometry
= true;
352 mbInsidePaint
= false;
356 mbSupportTextIndentingOnLineWidthChange
= false;
359 SdrGrafObj::SdrGrafObj(const Graphic
& rGrf
, const Rectangle
& rRect
)
360 : SdrRectObj ( rRect
),
361 pGraphicLink ( NULL
),
364 pGraphic
= new GraphicObject( rGrf
);
365 mpReplacementGraphic
= 0;
366 pGraphic
->SetSwapStreamHdl( LINK(this, SdrGrafObj
, ImpSwapHdl
) );
369 // #i118485# Shear allowed and possible now
372 mbGrafAnimationAllowed
= true;
375 mbLineIsOutsideGeometry
= true;
376 mbInsidePaint
= false;
380 mbSupportTextIndentingOnLineWidthChange
= false;
383 SdrGrafObj::SdrGrafObj( const Graphic
& rGrf
)
385 pGraphicLink ( NULL
),
388 pGraphic
= new GraphicObject( rGrf
);
389 mpReplacementGraphic
= 0;
390 pGraphic
->SetSwapStreamHdl( LINK(this, SdrGrafObj
, ImpSwapHdl
) );
393 // #i118485# Shear allowed and possible now
396 mbGrafAnimationAllowed
= true;
399 mbLineIsOutsideGeometry
= true;
400 mbInsidePaint
= false;
404 mbSupportTextIndentingOnLineWidthChange
= false;
407 SdrGrafObj::~SdrGrafObj()
410 delete mpReplacementGraphic
;
414 void SdrGrafObj::SetGraphicObject( const GraphicObject
& rGrfObj
)
417 delete mpReplacementGraphic
;
418 mpReplacementGraphic
= 0;
419 pGraphic
->SetSwapStreamHdl( LINK(this, SdrGrafObj
, ImpSwapHdl
) );
420 pGraphic
->SetUserData();
423 BroadcastObjectChange();
427 const GraphicObject
& SdrGrafObj::GetGraphicObject(bool bForceSwapIn
) const
437 const GraphicObject
* SdrGrafObj::GetReplacementGraphicObject() const
439 if(!mpReplacementGraphic
&& pGraphic
)
441 const SvgDataPtr
& rSvgDataPtr
= pGraphic
->GetGraphic().getSvgData();
443 if(rSvgDataPtr
.get())
445 const_cast< SdrGrafObj
* >(this)->mpReplacementGraphic
= new GraphicObject(rSvgDataPtr
->getReplacement());
449 return mpReplacementGraphic
;
452 void SdrGrafObj::NbcSetGraphic( const Graphic
& rGrf
)
454 pGraphic
->SetGraphic( rGrf
);
455 delete mpReplacementGraphic
;
456 mpReplacementGraphic
= 0;
457 pGraphic
->SetUserData();
462 void SdrGrafObj::SetGraphic( const Graphic
& rGrf
)
466 BroadcastObjectChange();
469 const Graphic
& SdrGrafObj::GetGraphic() const
472 return pGraphic
->GetGraphic();
475 Graphic
SdrGrafObj::GetTransformedGraphic( SdrGrafObjTransformsAttrs nTransformFlags
) const
477 // Refactored most of the code to GraphicObject, where
478 // everybody can use e.g. the cropping functionality
480 GraphicType eType
= GetGraphicType();
481 MapMode
aDestMap( pModel
->GetScaleUnit(), Point(), pModel
->GetScaleFraction(), pModel
->GetScaleFraction() );
482 const Size
aDestSize( GetLogicRect().GetSize() );
483 const bool bMirror
= bool( nTransformFlags
& SdrGrafObjTransformsAttrs::MIRROR
);
484 const bool bRotate
= bool( nTransformFlags
& SdrGrafObjTransformsAttrs::ROTATE
) &&
485 ( aGeo
.nRotationAngle
&& aGeo
.nRotationAngle
!= 18000 ) && ( GRAPHIC_NONE
!= eType
);
487 // Need cropping info earlier
488 const_cast<SdrGrafObj
*>(this)->ImpSetAttrToGrafInfo();
489 GraphicAttr aActAttr
;
491 if( SdrGrafObjTransformsAttrs::NONE
!= nTransformFlags
&&
492 GRAPHIC_NONE
!= eType
)
494 // Actually transform the graphic only in this case.
495 // Cropping always happens, though.
496 aActAttr
= aGrafInfo
;
500 sal_uInt16 nMirrorCase
= ( aGeo
.nRotationAngle
== 18000 ) ? ( bMirrored
? 3 : 4 ) : ( bMirrored
? 2 : 1 );
501 bool bHMirr
= nMirrorCase
== 2 || nMirrorCase
== 4;
502 bool bVMirr
= nMirrorCase
== 3 || nMirrorCase
== 4;
504 aActAttr
.SetMirrorFlags( ( bHMirr
? BmpMirrorFlags::Horizontal
: BmpMirrorFlags::NONE
) | ( bVMirr
? BmpMirrorFlags::Vertical
: BmpMirrorFlags::NONE
) );
508 aActAttr
.SetRotation( sal_uInt16(aGeo
.nRotationAngle
/ 10) );
511 // Delegate to moved code in GraphicObject
512 return GetGraphicObject().GetTransformedGraphic( aDestSize
, aDestMap
, aActAttr
);
515 GraphicType
SdrGrafObj::GetGraphicType() const
517 return pGraphic
->GetType();
520 bool SdrGrafObj::IsAnimated() const
522 return pGraphic
->IsAnimated();
525 bool SdrGrafObj::IsEPS() const
527 return pGraphic
->IsEPS();
530 bool SdrGrafObj::IsSwappedOut() const
532 return mbIsPreview
|| pGraphic
->IsSwappedOut();
535 const MapMode
& SdrGrafObj::GetGrafPrefMapMode() const
537 return pGraphic
->GetPrefMapMode();
540 const Size
& SdrGrafObj::GetGrafPrefSize() const
542 return pGraphic
->GetPrefSize();
545 void SdrGrafObj::SetGrafStreamURL( const OUString
& rGraphicStreamURL
)
548 if( rGraphicStreamURL
.isEmpty() )
550 pGraphic
->SetUserData();
552 else if( pModel
->IsSwapGraphics() )
554 pGraphic
->SetUserData( rGraphicStreamURL
);
558 OUString
SdrGrafObj::GetGrafStreamURL() const
560 return pGraphic
->GetUserData();
563 void SdrGrafObj::ForceSwapIn() const
565 if( mbIsPreview
&& pGraphic
->HasUserData() )
567 // removing preview graphic
568 const OUString
aUserData( pGraphic
->GetUserData() );
571 pGraphic
->SetGraphic( aEmpty
);
572 pGraphic
->SetUserData( aUserData
);
574 const_cast< SdrGrafObj
* >( this )->mbIsPreview
= false;
576 if ( pGraphicLink
&& pGraphic
->IsSwappedOut() )
577 ImpUpdateGraphicLink( false );
579 pGraphic
->FireSwapInRequest();
581 if( pGraphic
->IsSwappedOut() ||
582 ( pGraphic
->GetType() == GRAPHIC_NONE
) ||
583 ( pGraphic
->GetType() == GRAPHIC_DEFAULT
) )
585 Graphic aDefaultGraphic
;
586 aDefaultGraphic
.SetDefaultType();
587 pGraphic
->SetGraphic( aDefaultGraphic
);
591 void SdrGrafObj::ImpLinkAnmeldung()
593 sfx2::LinkManager
* pLinkManager
= pModel
!= NULL
? pModel
->GetLinkManager() : NULL
;
595 if( pLinkManager
!= NULL
&& pGraphicLink
== NULL
)
597 if (!aFileName
.isEmpty())
599 pGraphicLink
= new SdrGraphicLink( *this );
600 pLinkManager
->InsertFileLink(
601 *pGraphicLink
, OBJECT_CLIENT_GRF
, aFileName
, (aFilterName
.isEmpty() ? NULL
: &aFilterName
), NULL
);
602 pGraphicLink
->Connect();
607 void SdrGrafObj::ImpLinkAbmeldung()
609 sfx2::LinkManager
* pLinkManager
= pModel
!= NULL
? pModel
->GetLinkManager() : NULL
;
611 if( pLinkManager
!= NULL
&& pGraphicLink
!=NULL
)
613 // When using Remove, the *pGraphicLink is implicitly deleted
614 pLinkManager
->Remove( pGraphicLink
);
619 void SdrGrafObj::SetGraphicLink(const OUString
& rFileName
, const OUString
& rReferer
, const OUString
& rFilterName
)
622 aFileName
= rFileName
;
624 aFilterName
= rFilterName
;
626 pGraphic
->SetUserData();
627 pGraphic
->SetSwapState();
630 void SdrGrafObj::ReleaseGraphicLink()
638 bool SdrGrafObj::IsLinkedGraphic() const
640 return !aFileName
.isEmpty();
645 void SdrGrafObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
647 bool bNoPresGrf
= ( pGraphic
->GetType() != GRAPHIC_NONE
) && !bEmptyPresObj
;
649 rInfo
.bResizeFreeAllowed
= aGeo
.nRotationAngle
% 9000 == 0 ||
650 aGeo
.nRotationAngle
% 18000 == 0 ||
651 aGeo
.nRotationAngle
% 27000 == 0;
653 rInfo
.bResizePropAllowed
= true;
654 rInfo
.bRotateFreeAllowed
= bNoPresGrf
;
655 rInfo
.bRotate90Allowed
= bNoPresGrf
;
656 rInfo
.bMirrorFreeAllowed
= bNoPresGrf
;
657 rInfo
.bMirror45Allowed
= bNoPresGrf
;
658 rInfo
.bMirror90Allowed
= !bEmptyPresObj
;
659 rInfo
.bTransparenceAllowed
= false;
660 rInfo
.bGradientAllowed
= false;
662 // #i118485# Shear allowed and possible now
663 rInfo
.bShearAllowed
= true;
665 rInfo
.bEdgeRadiusAllowed
=false;
666 rInfo
.bCanConvToPath
= !IsEPS();
667 rInfo
.bCanConvToPathLineToArea
= false;
668 rInfo
.bCanConvToPolyLineToArea
= false;
669 rInfo
.bCanConvToPoly
= !IsEPS();
670 rInfo
.bCanConvToContour
= (rInfo
.bCanConvToPoly
|| LineGeometryUsageIsNecessary());
673 sal_uInt16
SdrGrafObj::GetObjIdentifier() const
675 return sal_uInt16( OBJ_GRAF
);
678 /* The graphic of the GraphicLink will be loaded. If it is called with
679 bAsynchron = true then the graphic will be set later via DataChanged
681 bool SdrGrafObj::ImpUpdateGraphicLink( bool bAsynchron
) const
687 pGraphicLink
->UpdateAsynchron();
689 pGraphicLink
->DataChanged( ImpLoadLinkedGraphic( aFileName
, aReferer
, aFilterName
) );
695 void SdrGrafObj::ImpSetLinkedGraphic( const Graphic
& rGraphic
)
697 const bool bIsChanged
= GetModel()->IsChanged();
698 NbcSetGraphic( rGraphic
);
700 BroadcastObjectChange();
701 GetModel()->SetChanged( bIsChanged
);
704 OUString
SdrGrafObj::TakeObjNameSingul() const
709 const SvgDataPtr
& rSvgDataPtr
= pGraphic
->GetGraphic().getSvgData();
711 OUStringBuffer sName
;
713 if(rSvgDataPtr
.get())
715 sName
.append(ImpGetResStr(STR_ObjNameSingulGRAFSVG
));
719 switch( pGraphic
->GetType() )
723 const sal_uInt16 nId
= ( ( pGraphic
->IsTransparent() || static_cast<const SdrGrafTransparenceItem
&>( GetObjectItem( SDRATTR_GRAFTRANSPARENCE
) ).GetValue() ) ?
724 ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPTRANSLNK
: STR_ObjNameSingulGRAFBMPTRANS
) :
725 ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPLNK
: STR_ObjNameSingulGRAFBMP
) );
727 sName
.append(ImpGetResStr(nId
));
731 case GRAPHIC_GDIMETAFILE
:
732 sName
.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNK
: STR_ObjNameSingulGRAFMTF
));
736 sName
.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNK
: STR_ObjNameSingulGRAFNONE
));
740 sName
.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNK
: STR_ObjNameSingulGRAF
));
745 const OUString
aName(GetName());
747 if (!aName
.isEmpty())
754 return sName
.makeStringAndClear();
757 OUString
SdrGrafObj::TakeObjNamePlural() const
762 const SvgDataPtr
& rSvgDataPtr
= pGraphic
->GetGraphic().getSvgData();
764 OUStringBuffer sName
;
766 if(rSvgDataPtr
.get())
768 sName
.append(ImpGetResStr(STR_ObjNamePluralGRAFSVG
));
772 switch( pGraphic
->GetType() )
776 const sal_uInt16 nId
= ( ( pGraphic
->IsTransparent() || static_cast<const SdrGrafTransparenceItem
&>( GetObjectItem( SDRATTR_GRAFTRANSPARENCE
) ).GetValue() ) ?
777 ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPTRANSLNK
: STR_ObjNamePluralGRAFBMPTRANS
) :
778 ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPLNK
: STR_ObjNamePluralGRAFBMP
) );
780 sName
.append(ImpGetResStr(nId
));
784 case GRAPHIC_GDIMETAFILE
:
785 sName
.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNK
: STR_ObjNamePluralGRAFMTF
));
789 sName
.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNK
: STR_ObjNamePluralGRAFNONE
));
793 sName
.append(ImpGetResStr(IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNK
: STR_ObjNamePluralGRAF
));
798 const OUString
aName(GetName());
800 if (!aName
.isEmpty())
807 return sName
.makeStringAndClear();
810 SdrObject
* SdrGrafObj::getFullDragClone() const
813 SdrGrafObj
* pRetval
= static_cast< SdrGrafObj
* >(SdrRectObj::getFullDragClone());
815 // #i103116# the full drag clone leads to problems
816 // with linked graphics, so reset the link in this
817 // temporary interaction object and load graphic
818 if(pRetval
&& IsLinkedGraphic())
820 pRetval
->ForceSwapIn();
821 pRetval
->ReleaseGraphicLink();
827 SdrGrafObj
* SdrGrafObj::Clone() const
829 return CloneHelper
< SdrGrafObj
>();
832 SdrGrafObj
& SdrGrafObj::operator=( const SdrGrafObj
& rObj
)
836 SdrRectObj::operator=( rObj
);
838 pGraphic
->SetGraphic( rObj
.GetGraphic(), &rObj
.GetGraphicObject() );
839 aFileName
= rObj
.aFileName
;
840 aFilterName
= rObj
.aFilterName
;
841 bMirrored
= rObj
.bMirrored
;
843 if( rObj
.IsLinkedGraphic() )
845 SetGraphicLink( aFileName
, rObj
.aReferer
, aFilterName
);
848 ImpSetAttrToGrafInfo();
852 basegfx::B2DPolyPolygon
SdrGrafObj::TakeXorPoly() const
856 basegfx::B2DPolyPolygon aRetval
;
858 // take grown rectangle
859 const sal_Int32
nHalfLineWidth(ImpGetLineWdt() / 2);
860 const Rectangle
aGrownRect(
861 maRect
.Left() - nHalfLineWidth
,
862 maRect
.Top() - nHalfLineWidth
,
863 maRect
.Right() + nHalfLineWidth
,
864 maRect
.Bottom() + nHalfLineWidth
);
866 XPolygon
aXPoly(ImpCalcXPoly(aGrownRect
, GetEckenradius()));
867 aRetval
.append(aXPoly
.getB2DPolygon());
874 return SdrRectObj::TakeXorPoly();
878 sal_uInt32
SdrGrafObj::GetHdlCount() const
883 SdrHdl
* SdrGrafObj::GetHdl(sal_uInt32 nHdlNum
) const
885 return SdrRectObj::GetHdl( nHdlNum
+ 1L );
888 void SdrGrafObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
890 SdrRectObj::NbcResize( rRef
, xFact
, yFact
);
892 bool bMirrX
= xFact
.GetNumerator() < 0;
893 bool bMirrY
= yFact
.GetNumerator() < 0;
895 if( bMirrX
!= bMirrY
)
896 bMirrored
= !bMirrored
;
899 void SdrGrafObj::NbcRotate(const Point
& rRef
, long nAngle
, double sn
, double cs
)
901 SdrRectObj::NbcRotate(rRef
,nAngle
,sn
,cs
);
904 void SdrGrafObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
906 SdrRectObj::NbcMirror(rRef1
,rRef2
);
907 bMirrored
= !bMirrored
;
910 void SdrGrafObj::NbcShear(const Point
& rRef
, long nAngle
, double tn
, bool bVShear
)
912 // #i118485# Call Shear now, old version redirected to rotate
913 SdrRectObj::NbcShear(rRef
, nAngle
, tn
, bVShear
);
916 void SdrGrafObj::NbcSetSnapRect(const Rectangle
& rRect
)
918 SdrRectObj::NbcSetSnapRect(rRect
);
921 void SdrGrafObj::NbcSetLogicRect( const Rectangle
& rRect
)
923 SdrRectObj::NbcSetLogicRect(rRect
);
926 SdrObjGeoData
* SdrGrafObj::NewGeoData() const
928 return new SdrGrafObjGeoData
;
931 void SdrGrafObj::SaveGeoData(SdrObjGeoData
& rGeo
) const
933 SdrRectObj::SaveGeoData(rGeo
);
934 SdrGrafObjGeoData
& rGGeo
=static_cast<SdrGrafObjGeoData
&>(rGeo
);
935 rGGeo
.bMirrored
=bMirrored
;
938 void SdrGrafObj::RestGeoData(const SdrObjGeoData
& rGeo
)
940 SdrRectObj::RestGeoData(rGeo
);
941 const SdrGrafObjGeoData
& rGGeo
=static_cast<const SdrGrafObjGeoData
&>(rGeo
);
942 bMirrored
=rGGeo
.bMirrored
;
945 void SdrGrafObj::SetPage( SdrPage
* pNewPage
)
947 bool bRemove
= pNewPage
== NULL
&& pPage
!= NULL
;
948 bool bInsert
= pNewPage
!= NULL
&& pPage
== NULL
;
952 // No SwapIn necessary here, because if something's not loaded, it can't be animated either.
953 if( pGraphic
->IsAnimated())
954 pGraphic
->StopAnimation();
956 if( pGraphicLink
!= NULL
)
960 if(!pModel
&& !GetStyleSheet() && pNewPage
&& pNewPage
->GetModel())
962 // #i119287# Set default StyleSheet for SdrGrafObj here, it is different from 'Default'. This
963 // needs to be done before the style 'Default' is set from the :SetModel() call which is triggered
964 // from the following :SetPage().
965 // TTTT: Needs to be moved in branch aw080 due to having a SdrModel from the beginning, is at this
966 // place for convenience currently (works in both versions, is not in the way)
967 SfxStyleSheet
* pSheet
= pNewPage
->GetModel()->GetDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj();
971 SetStyleSheet(pSheet
, false);
975 SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE
));
976 SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE
));
980 SdrRectObj::SetPage( pNewPage
);
982 if (!aFileName
.isEmpty() && bInsert
)
986 void SdrGrafObj::SetModel( SdrModel
* pNewModel
)
988 bool bChg
= pNewModel
!= pModel
;
992 if( pGraphic
->HasUserData() )
997 if( pGraphicLink
!= NULL
)
1002 SdrRectObj::SetModel(pNewModel
);
1004 if (bChg
&& !aFileName
.isEmpty())
1008 void SdrGrafObj::StartAnimation( OutputDevice
* /*pOutDev*/, const Point
& /*rPoint*/, const Size
& /*rSize*/, long /*nExtraData*/)
1010 SetGrafAnimationAllowed(true);
1013 bool SdrGrafObj::HasGDIMetaFile() const
1015 return( pGraphic
->GetType() == GRAPHIC_GDIMETAFILE
);
1018 bool SdrGrafObj::isEmbeddedSvg() const
1020 return GRAPHIC_BITMAP
== GetGraphicType() && GetGraphic().getSvgData().get();
1023 GDIMetaFile
SdrGrafObj::getMetafileFromEmbeddedSvg() const
1025 GDIMetaFile aRetval
;
1027 if(isEmbeddedSvg() && GetModel())
1029 ScopedVclPtrInstance
< VirtualDevice
> pOut
;
1030 const Rectangle
aBoundRect(GetCurrentBoundRect());
1031 const MapMode
aMap(GetModel()->GetScaleUnit(), Point(), GetModel()->GetScaleFraction(), GetModel()->GetScaleFraction());
1033 pOut
->EnableOutput(false);
1034 pOut
->SetMapMode(aMap
);
1035 aRetval
.Record(pOut
);
1036 SingleObjectPainter(*pOut
.get());
1038 aRetval
.WindStart();
1039 aRetval
.Move(-aBoundRect
.Left(), -aBoundRect
.Top());
1040 aRetval
.SetPrefMapMode(aMap
);
1041 aRetval
.SetPrefSize(aBoundRect
.GetSize());
1047 SdrObject
* SdrGrafObj::DoConvertToPolyObj(bool bBezier
, bool bAddText
) const
1049 SdrObject
* pRetval
= NULL
;
1050 GraphicType
aGraphicType(GetGraphicType());
1056 // There is currently no helper to create SdrObjects from primitives (even if I'm thinking
1057 // about writing one for some time). To get the roundtrip to SdrObjects it is necessary to
1058 // use the old converter path over the MetaFile mechanism. Create Metafile from Svg
1059 // primitives here pretty directly
1060 aMtf
= getMetafileFromEmbeddedSvg();
1061 aGraphicType
= GRAPHIC_GDIMETAFILE
;
1063 else if(GRAPHIC_GDIMETAFILE
== aGraphicType
)
1065 aMtf
= GetTransformedGraphic(SdrGrafObjTransformsAttrs::COLOR
|SdrGrafObjTransformsAttrs::MIRROR
).GetGDIMetaFile();
1068 switch(aGraphicType
)
1070 case GRAPHIC_GDIMETAFILE
:
1072 // Sort into group and return ONLY those objects that can be created from the MetaFile.
1073 ImpSdrGDIMetaFileImport
aFilter(*GetModel(), GetLayer(), maRect
);
1074 SdrObjGroup
* pGrp
= new SdrObjGroup();
1076 if(aFilter
.DoImport(aMtf
, *pGrp
->GetSubList(), 0))
1079 // copy transformation
1080 GeoStat
aGeoStat(GetGeoStat());
1082 if(aGeoStat
.nShearAngle
)
1084 aGeoStat
.RecalcTan();
1085 pGrp
->NbcShear(maRect
.TopLeft(), aGeoStat
.nShearAngle
, aGeoStat
.nTan
, false);
1088 if(aGeoStat
.nRotationAngle
)
1090 aGeoStat
.RecalcSinCos();
1091 pGrp
->NbcRotate(maRect
.TopLeft(), aGeoStat
.nRotationAngle
, aGeoStat
.nSin
, aGeoStat
.nCos
);
1096 pGrp
->NbcSetLayer(GetLayer());
1097 pGrp
->SetModel(GetModel());
1101 pRetval
= ImpConvertAddText(pRetval
, bBezier
);
1104 // convert all children
1107 SdrObject
* pHalfDone
= pRetval
;
1108 pRetval
= pHalfDone
->DoConvertToPolyObj(bBezier
, bAddText
);
1109 SdrObject::Free( pHalfDone
); // resulting object is newly created
1113 // flatten subgroups. As we call
1114 // DoConvertToPolyObj() on the resulting group
1115 // objects, subgroups can exist (e.g. text is
1116 // a group object for every line).
1117 SdrObjList
* pList
= pRetval
->GetSubList();
1119 pList
->FlattenGroups();
1128 // #i118485# convert line and fill
1129 SdrObject
* pLineFill
= SdrRectObj::DoConvertToPolyObj(bBezier
, false);
1135 pGrp
= dynamic_cast< SdrObjGroup
* >(pRetval
);
1139 pGrp
= new SdrObjGroup();
1141 pGrp
->NbcSetLayer(GetLayer());
1142 pGrp
->SetModel(GetModel());
1143 pGrp
->GetSubList()->NbcInsertObject(pRetval
);
1146 pGrp
->GetSubList()->NbcInsertObject(pLineFill
, 0);
1150 pRetval
= pLineFill
;
1156 case GRAPHIC_BITMAP
:
1158 // create basic object and add fill
1159 pRetval
= SdrRectObj::DoConvertToPolyObj(bBezier
, bAddText
);
1161 // save bitmap as an attribute
1164 // retrieve bitmap for the fill
1165 SfxItemSet
aSet(GetObjectItemSet());
1167 aSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
1168 const BitmapEx
aBitmapEx(GetTransformedGraphic().GetBitmapEx());
1169 aSet
.Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx
)));
1170 aSet
.Put(XFillBmpTileItem(false));
1172 pRetval
->SetMergedItemSet(aSet
);
1177 case GRAPHIC_DEFAULT
:
1179 pRetval
= SdrRectObj::DoConvertToPolyObj(bBezier
, bAddText
);
1187 void SdrGrafObj::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
1190 SdrRectObj::Notify( rBC
, rHint
);
1191 ImpSetAttrToGrafInfo();
1195 void SdrGrafObj::SetMirrored( bool _bMirrored
)
1197 bMirrored
= _bMirrored
;
1200 void SdrGrafObj::ImpSetAttrToGrafInfo()
1202 const SfxItemSet
& rSet
= GetObjectItemSet();
1203 const sal_uInt16 nTrans
= static_cast<const SdrGrafTransparenceItem
&>( rSet
.Get( SDRATTR_GRAFTRANSPARENCE
) ).GetValue();
1204 const SdrGrafCropItem
& rCrop
= static_cast<const SdrGrafCropItem
&>( rSet
.Get( SDRATTR_GRAFCROP
) );
1206 aGrafInfo
.SetLuminance( static_cast<const SdrGrafLuminanceItem
&>( rSet
.Get( SDRATTR_GRAFLUMINANCE
) ).GetValue() );
1207 aGrafInfo
.SetContrast( static_cast<const SdrGrafContrastItem
&>( rSet
.Get( SDRATTR_GRAFCONTRAST
) ).GetValue() );
1208 aGrafInfo
.SetChannelR( static_cast<const SdrGrafRedItem
&>( rSet
.Get( SDRATTR_GRAFRED
) ).GetValue() );
1209 aGrafInfo
.SetChannelG( static_cast<const SdrGrafGreenItem
&>( rSet
.Get( SDRATTR_GRAFGREEN
) ).GetValue() );
1210 aGrafInfo
.SetChannelB( static_cast<const SdrGrafBlueItem
&>( rSet
.Get( SDRATTR_GRAFBLUE
) ).GetValue() );
1211 aGrafInfo
.SetGamma( static_cast<const SdrGrafGamma100Item
&>( rSet
.Get( SDRATTR_GRAFGAMMA
) ).GetValue() * 0.01 );
1212 aGrafInfo
.SetTransparency( (sal_uInt8
) FRound( std::min( nTrans
, (sal_uInt16
) 100 ) * 2.55 ) );
1213 aGrafInfo
.SetInvert( static_cast<const SdrGrafInvertItem
&>( rSet
.Get( SDRATTR_GRAFINVERT
) ).GetValue() );
1214 aGrafInfo
.SetDrawMode( static_cast<const SdrGrafModeItem
&>( rSet
.Get( SDRATTR_GRAFMODE
) ).GetValue() );
1215 aGrafInfo
.SetCrop( rCrop
.GetLeft(), rCrop
.GetTop(), rCrop
.GetRight(), rCrop
.GetBottom() );
1221 void SdrGrafObj::AdjustToMaxRect( const Rectangle
& rMaxRect
, bool bShrinkOnly
)
1224 Size
aMaxSize( rMaxRect
.GetSize() );
1225 if ( pGraphic
->GetPrefMapMode().GetMapUnit() == MAP_PIXEL
)
1226 aSize
= Application::GetDefaultDevice()->PixelToLogic( pGraphic
->GetPrefSize(), MAP_100TH_MM
);
1228 aSize
= OutputDevice::LogicToLogic( pGraphic
->GetPrefSize(),
1229 pGraphic
->GetPrefMapMode(),
1230 MapMode( MAP_100TH_MM
) );
1232 if( aSize
.Height() != 0 && aSize
.Width() != 0 )
1234 Point
aPos( rMaxRect
.TopLeft() );
1236 // if the graphic is too large, fit it to page
1237 if ( (!bShrinkOnly
||
1238 ( aSize
.Height() > aMaxSize
.Height() ) ||
1239 ( aSize
.Width() > aMaxSize
.Width() ) )&&
1240 aSize
.Height() && aMaxSize
.Height() )
1242 float fGrfWH
= (float)aSize
.Width() /
1243 (float)aSize
.Height();
1244 float fWinWH
= (float)aMaxSize
.Width() /
1245 (float)aMaxSize
.Height();
1247 // Scale graphic to page size
1248 if ( fGrfWH
< fWinWH
)
1250 aSize
.Width() = (long)(aMaxSize
.Height() * fGrfWH
);
1251 aSize
.Height()= aMaxSize
.Height();
1253 else if ( fGrfWH
> 0.F
)
1255 aSize
.Width() = aMaxSize
.Width();
1256 aSize
.Height()= (long)(aMaxSize
.Width() / fGrfWH
);
1259 aPos
= rMaxRect
.Center();
1263 aPos
= maRect
.TopLeft();
1265 aPos
.X() -= aSize
.Width() / 2;
1266 aPos
.Y() -= aSize
.Height() / 2;
1267 SetLogicRect( Rectangle( aPos
, aSize
) );
1271 IMPL_LINK( SdrGrafObj
, ImpSwapHdl
, GraphicObject
*, pO
)
1273 SvStream
* pRet
= GRFMGR_AUTOSWAPSTREAM_NONE
;
1275 if( pO
->IsInSwapOut() )
1277 if( pModel
&& !mbIsPreview
&& pModel
->IsSwapGraphics() && pGraphic
->GetSizeBytes() > 20480 )
1279 // test if this object is visualized from someone
1280 // ## test only if there are VOCs other than the preview renderer
1281 if(!GetViewContact().HasViewObjectContacts(true))
1283 const SdrSwapGraphicsMode nSwapMode
= pModel
->GetSwapGraphicsMode();
1285 if( ( pGraphicLink
) &&
1286 ( nSwapMode
& SdrSwapGraphicsMode::PURGE
) )
1288 pRet
= GRFMGR_AUTOSWAPSTREAM_LINK
;
1290 else if( nSwapMode
& SdrSwapGraphicsMode::TEMP
)
1292 pRet
= GRFMGR_AUTOSWAPSTREAM_TEMP
;
1293 pGraphic
->SetUserData();
1297 sdr::contact::ViewContactOfGraphic
* pVC
= dynamic_cast< sdr::contact::ViewContactOfGraphic
* >(&GetViewContact());
1301 pVC
->flushGraphicObjects();
1306 else if( pO
->IsInSwapIn() )
1308 // can be loaded from the original document stream later
1309 if( pModel
!= NULL
)
1311 if( pGraphic
->HasUserData() )
1313 ::comphelper::LifecycleProxy proxy
;
1314 OUString aUserData
= pGraphic
->GetUserData();
1315 uno::Reference
<io::XInputStream
> const xStream(
1316 pModel
->GetDocumentStream(aUserData
, proxy
));
1318 ::boost::scoped_ptr
<SvStream
> const pStream( (xStream
.is())
1319 ? ::utl::UcbStreamHelper::CreateStream(xStream
)
1326 boost::scoped_ptr
<com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> > pFilterData
;
1328 if(mbInsidePaint
&& !GetViewContact().HasViewObjectContacts(true))
1330 pFilterData
.reset(new com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
>( 3 ));
1332 const com::sun::star::awt::Size
aPreviewSizeHint( 64, 64 );
1333 const bool bAllowPartialStreamRead
= true;
1334 // create <GfxLink> instance also for previews in order to avoid that its corresponding
1335 // data is cleared in the graphic cache entry in case that the preview data equals the complete graphic data
1336 const bool bCreateNativeLink
= true;
1337 (*pFilterData
)[ 0 ].Name
= "PreviewSizeHint";
1338 (*pFilterData
)[ 0 ].Value
<<= aPreviewSizeHint
;
1339 (*pFilterData
)[ 1 ].Name
= "AllowPartialStreamRead";
1340 (*pFilterData
)[ 1 ].Value
<<= bAllowPartialStreamRead
;
1341 (*pFilterData
)[ 2 ].Name
= "CreateNativeLink";
1342 (*pFilterData
)[ 2 ].Value
<<= bCreateNativeLink
;
1347 if(!GraphicFilter::GetGraphicFilter().ImportGraphic(
1348 aGraphic
, aUserData
, *pStream
,
1349 GRFILTER_FORMAT_DONTKNOW
, NULL
, GraphicFilterImportFlags::NONE
, pFilterData
.get()))
1351 const OUString
aNewUserData( pGraphic
->GetUserData() );
1352 pGraphic
->SetGraphic( aGraphic
);
1355 pGraphic
->SetUserData(aNewUserData
);
1359 pGraphic
->SetUserData();
1362 // Graphic successfully swapped in.
1363 pRet
= GRFMGR_AUTOSWAPSTREAM_LOADED
;
1365 pFilterData
.reset();
1367 pStream
->ResetError();
1370 else if( !ImpUpdateGraphicLink( false ) )
1372 pRet
= GRFMGR_AUTOSWAPSTREAM_TEMP
;
1376 pRet
= GRFMGR_AUTOSWAPSTREAM_LOADED
;
1380 pRet
= GRFMGR_AUTOSWAPSTREAM_TEMP
;
1383 return reinterpret_cast<sal_IntPtr
>(pRet
);
1386 void SdrGrafObj::SetGrafAnimationAllowed(bool bNew
)
1388 if(mbGrafAnimationAllowed
!= bNew
)
1390 mbGrafAnimationAllowed
= bNew
;
1395 Reference
< XInputStream
> SdrGrafObj::getInputStream()
1397 Reference
< XInputStream
> xStream
;
1401 if( pGraphic
&& GetGraphic().IsLink() )
1403 Graphic
aGraphic( GetGraphic() );
1404 GfxLink
aLink( aGraphic
.GetLink() );
1405 sal_uInt32 nSize
= aLink
.GetDataSize();
1406 const void* pSourceData
= (const void*)aLink
.GetData();
1407 if( nSize
&& pSourceData
)
1409 sal_uInt8
* pBuffer
= new sal_uInt8
[ nSize
];
1410 memcpy( pBuffer
, pSourceData
, nSize
);
1412 SvMemoryStream
* pStream
= new SvMemoryStream( (void*)pBuffer
, (sal_Size
)nSize
, StreamMode::READ
);
1413 pStream
->ObjectOwnsMemory( true );
1414 xStream
.set( new utl::OInputStreamWrapper( pStream
, true ) );
1418 if (!xStream
.is() && !aFileName
.isEmpty())
1420 SvFileStream
* pStream
= new SvFileStream( aFileName
, StreamMode::READ
);
1421 xStream
.set( new utl::OInputStreamWrapper( pStream
) );
1428 // moved crop handle creation here; this is the object type using them
1429 void SdrGrafObj::addCropHandles(SdrHdlList
& rTarget
) const
1431 basegfx::B2DHomMatrix aMatrix
;
1432 basegfx::B2DPolyPolygon aPolyPolygon
;
1434 // get object transformation
1435 TRGetBaseGeometry(aMatrix
, aPolyPolygon
);
1437 // part of object transformation correction, but used later, so defined outside next scope
1438 double fShearX(0.0), fRotate(0.0);
1440 { // TTTT correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080
1441 basegfx::B2DTuple aScale
;
1442 basegfx::B2DTuple aTranslate
;
1444 aMatrix
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
1446 if(!basegfx::fTools::equalZero(fShearX
))
1448 // shearX is used, correct it
1452 aMatrix
= basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
1460 const SdrGrafCropItem
& rCrop
= static_cast< const SdrGrafCropItem
& >(GetMergedItem(SDRATTR_GRAFCROP
));
1462 if(rCrop
.GetLeft() || rCrop
.GetTop() || rCrop
.GetRight() ||rCrop
.GetBottom())
1464 // decompose object transformation to have current translate and scale
1465 basegfx::B2DVector aScale
, aTranslate
;
1466 double fLclRotate
, fLclShearX
;
1468 aMatrix
.decompose(aScale
, aTranslate
, fLclRotate
, fLclShearX
);
1470 if(!aScale
.equalZero())
1473 const basegfx::B2DVector
aCropScaleFactor(
1474 GetGraphicObject().calculateCropScaling(
1480 rCrop
.GetBottom()));
1483 const double fCropLeft(rCrop
.GetLeft() * aCropScaleFactor
.getX());
1484 const double fCropTop(rCrop
.GetTop() * aCropScaleFactor
.getY());
1485 const double fCropRight(rCrop
.GetRight() * aCropScaleFactor
.getX());
1486 const double fCropBottom(rCrop
.GetBottom() * aCropScaleFactor
.getY());
1487 basegfx::B2DHomMatrix
aMatrixForCropViewHdl(aMatrix
);
1491 // create corrected new matrix, TTTT can be removed with aw080
1492 // the old mirror only can mirror horizontally; the vertical mirror
1493 // is faked by using the horizontal and 180 degree rotation. Since
1494 // the object can be rotated differently from 180 degree, this is
1495 // not safe to detect. Just correct horizontal mirror (which is
1496 // in IsMirrored()) and keep the rotation angle
1497 // caution: Do not modify aMatrix, it is used below to calculate
1498 // the exact handle positions
1499 basegfx::B2DHomMatrix aPreMultiply
;
1501 // mirrored X, apply
1502 aPreMultiply
.translate(-0.5, 0.0);
1503 aPreMultiply
.scale(-1.0, 1.0);
1504 aPreMultiply
.translate(0.5, 0.0);
1506 aMatrixForCropViewHdl
= aMatrixForCropViewHdl
* aPreMultiply
;
1511 aMatrixForCropViewHdl
,
1512 GetGraphicObject().GetGraphic(),
1520 basegfx::B2DPoint aPos
;
1522 aPos
= aMatrix
* basegfx::B2DPoint(0.0, 0.0);
1523 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), HDL_UPLFT
, fShearX
, fRotate
));
1524 aPos
= aMatrix
* basegfx::B2DPoint(0.5, 0.0);
1525 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), HDL_UPPER
, fShearX
, fRotate
));
1526 aPos
= aMatrix
* basegfx::B2DPoint(1.0, 0.0);
1527 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), HDL_UPRGT
, fShearX
, fRotate
));
1528 aPos
= aMatrix
* basegfx::B2DPoint(0.0, 0.5);
1529 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), HDL_LEFT
, fShearX
, fRotate
));
1530 aPos
= aMatrix
* basegfx::B2DPoint(1.0, 0.5);
1531 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), HDL_RIGHT
, fShearX
, fRotate
));
1532 aPos
= aMatrix
* basegfx::B2DPoint(0.0, 1.0);
1533 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), HDL_LWLFT
, fShearX
, fRotate
));
1534 aPos
= aMatrix
* basegfx::B2DPoint(0.5, 1.0);
1535 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), HDL_LOWER
, fShearX
, fRotate
));
1536 aPos
= aMatrix
* basegfx::B2DPoint(1.0, 1.0);
1537 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), HDL_LWRGT
, fShearX
, fRotate
));
1540 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */