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 "svx/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 <svx/sdr/properties/graphicproperties.hxx>
57 #include <svx/sdr/contact/viewcontactofgraphic.hxx>
58 #include <basegfx/polygon/b2dpolygon.hxx>
59 #include <basegfx/polygon/b2dpolygontools.hxx>
60 #include <osl/thread.hxx>
61 #include <drawinglayer/processor2d/objectinfoextractor2d.hxx>
62 #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
64 using namespace ::com::sun::star
;
65 using namespace ::com::sun::star::uno
;
66 using namespace ::com::sun::star::io
;
68 #define SWAPGRAPHIC_TIMEOUT 5000
70 const Graphic
ImpLoadLinkedGraphic( const String aFileName
, const String aFilterName
)
74 SfxMedium
xMed( aFileName
, 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
.Len() && rGF
.GetImportFormatCount()
84 ? rGF
.GetImportFormatNumber( aFilterName
)
85 : GRFILTER_FORMAT_DONTKNOW
;
88 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aFilterData( 1 );
90 // TODO: Room for improvement:
91 // As this is a linked graphic the GfxLink is not needed if saving/loading our own format.
92 // But this link is required by some filters to access the native graphic (PDF export/MS export),
93 // there we should create a new service to provide this data if needed
94 aFilterData
[ 0 ].Name
= OUString( "CreateNativeLink" );
95 aFilterData
[ 0 ].Value
= Any( true );
96 rGF
.ImportGraphic( aGraphic
, aEmptyStr
, *pInStrm
, nFilter
, NULL
, 0, &aFilterData
);
101 class SdrGraphicUpdater
;
102 class SdrGraphicLink
: public sfx2::SvBaseLink
104 SdrGrafObj
* pGrafObj
;
105 SdrGraphicUpdater
* pGraphicUpdater
;
108 SdrGraphicLink(SdrGrafObj
* pObj
);
109 virtual ~SdrGraphicLink();
111 virtual void Closed();
113 virtual ::sfx2::SvBaseLink::UpdateResult
DataChanged(
114 const String
& rMimeType
, const ::com::sun::star::uno::Any
& rValue
);
115 void DataChanged( const Graphic
& rGraphic
);
117 bool Connect() { return 0 != GetRealObject(); }
118 void UpdateAsynchron();
119 void RemoveGraphicUpdater();
122 class SdrGraphicUpdater
: public ::osl::Thread
125 SdrGraphicUpdater( const String
& rFileName
, const String
& rFilterName
, SdrGraphicLink
& );
126 virtual ~SdrGraphicUpdater( void );
128 void SAL_CALL
Terminate( void );
130 bool GraphicLinkChanged( const String
& rFileName
){ return maFileName
!= rFileName
; };
134 /** is called from the inherited create method and acts as the
135 main function of this thread.
137 virtual void SAL_CALL
run(void);
139 /** Called after the thread is terminated via the terminate
140 method. Used to kill the thread by calling delete on this.
142 virtual void SAL_CALL
onTerminated(void);
146 const String maFileName
;
147 const String maFilterName
;
148 SdrGraphicLink
& mrGraphicLink
;
150 volatile bool mbIsTerminated
;
153 SdrGraphicUpdater::SdrGraphicUpdater( const String
& rFileName
, const String
& rFilterName
, SdrGraphicLink
& rGraphicLink
)
154 : maFileName( rFileName
)
155 , maFilterName( rFilterName
)
156 , mrGraphicLink( rGraphicLink
)
157 , mbIsTerminated( false )
162 SdrGraphicUpdater::~SdrGraphicUpdater( void )
166 void SdrGraphicUpdater::Terminate()
168 mbIsTerminated
= true;
171 void SAL_CALL
SdrGraphicUpdater::onTerminated(void)
176 void SAL_CALL
SdrGraphicUpdater::run(void)
178 Graphic
aGraphic( ImpLoadLinkedGraphic( maFileName
, maFilterName
) );
179 SolarMutexGuard aSolarGuard
;
180 if ( !mbIsTerminated
)
182 mrGraphicLink
.DataChanged( aGraphic
);
183 mrGraphicLink
.RemoveGraphicUpdater();
187 SdrGraphicLink::SdrGraphicLink(SdrGrafObj
* pObj
)
188 : ::sfx2::SvBaseLink( ::sfx2::LINKUPDATE_ONCALL
, SOT_FORMATSTR_ID_SVXB
)
190 , pGraphicUpdater( NULL
)
192 SetSynchron( false );
195 SdrGraphicLink::~SdrGraphicLink()
197 if ( pGraphicUpdater
)
198 pGraphicUpdater
->Terminate();
201 void SdrGraphicLink::DataChanged( const Graphic
& rGraphic
)
203 pGrafObj
->ImpSetLinkedGraphic( rGraphic
);
206 void SdrGraphicLink::RemoveGraphicUpdater()
208 pGraphicUpdater
= NULL
;
211 ::sfx2::SvBaseLink::UpdateResult
SdrGraphicLink::DataChanged(
212 const String
& rMimeType
, const ::com::sun::star::uno::Any
& rValue
)
214 SdrModel
* pModel
= pGrafObj
? pGrafObj
->GetModel() : 0;
215 sfx2::LinkManager
* pLinkManager
= pModel
? pModel
->GetLinkManager() : 0;
217 if( pLinkManager
&& rValue
.hasValue() )
219 pLinkManager
->GetDisplayNames( this, 0, &pGrafObj
->aFileName
, 0, &pGrafObj
->aFilterName
);
222 if( sfx2::LinkManager::GetGraphicFromAny( rMimeType
, rValue
, aGraphic
))
224 pGrafObj
->NbcSetGraphic( aGraphic
);
225 pGrafObj
->ActionChanged();
227 else if( SotExchange::GetFormatIdFromMimeType( rMimeType
) != sfx2::LinkManager::RegisterStatusInfoId() )
229 // broadcasting, to update slide sorter
230 pGrafObj
->BroadcastObjectChange();
236 void SdrGraphicLink::Closed()
238 // close connection; set pLink of the object to NULL, as link instance is just about getting destructed.
239 pGrafObj
->ForceSwapIn();
240 pGrafObj
->pGraphicLink
=NULL
;
241 pGrafObj
->ReleaseGraphicLink();
242 SvBaseLink::Closed();
245 void SdrGraphicLink::UpdateAsynchron()
249 if ( pGraphicUpdater
)
251 if ( pGraphicUpdater
->GraphicLinkChanged( pGrafObj
->GetFileName() ) )
253 pGraphicUpdater
->Terminate();
254 pGraphicUpdater
= new SdrGraphicUpdater( pGrafObj
->GetFileName(), pGrafObj
->GetFilterName(), *this );
258 pGraphicUpdater
= new SdrGraphicUpdater( pGrafObj
->GetFileName(), pGrafObj
->GetFilterName(), *this );
262 sdr::properties::BaseProperties
* SdrGrafObj::CreateObjectSpecificProperties()
264 return new sdr::properties::GraphicProperties(*this);
267 //////////////////////////////////////////////////////////////////////////////
268 // DrawContact section
270 sdr::contact::ViewContact
* SdrGrafObj::CreateObjectSpecificViewContact()
272 return new sdr::contact::ViewContactOfGraphic(*this);
275 //////////////////////////////////////////////////////////////////////////////
276 // check if SVG and if try to get ObjectInfoPrimitive2D and extract info
278 void SdrGrafObj::onGraphicChanged()
280 if (!pGraphic
|| pGraphic
->IsSwappedOut()) // don't force swap-in for this
289 const SvgDataPtr
& rSvgDataPtr
= pGraphic
->GetGraphic().getSvgData();
291 if(rSvgDataPtr
.get())
293 const drawinglayer::primitive2d::Primitive2DSequence
aSequence(rSvgDataPtr
->getPrimitive2DSequence());
295 if(aSequence
.hasElements())
297 drawinglayer::geometry::ViewInformation2D aViewInformation2D
;
298 drawinglayer::processor2d::ObjectInfoPrimitiveExtractor2D
aProcessor(aViewInformation2D
);
300 aProcessor
.process(aSequence
);
302 const drawinglayer::primitive2d::ObjectInfoPrimitive2D
* pResult
= aProcessor
.getResult();
306 aName
= pResult
->getName();
307 aTitle
= pResult
->getTitle();
308 aDesc
= pResult
->getDesc();
326 SetDescription(aDesc
);
330 TYPEINIT1(SdrGrafObj
,SdrRectObj
);
332 SdrGrafObj::SdrGrafObj()
334 pGraphicLink ( NULL
),
337 pGraphic
= new GraphicObject
;
338 mpReplacementGraphic
= 0;
339 pGraphic
->SetSwapStreamHdl( LINK( this, SdrGrafObj
, ImpSwapHdl
), SWAPGRAPHIC_TIMEOUT
);
342 // #i118485# Shear allowed and possible now
345 mbGrafAnimationAllowed
= true;
348 mbLineIsOutsideGeometry
= true;
349 mbInsidePaint
= false;
353 mbSupportTextIndentingOnLineWidthChange
= false;
356 SdrGrafObj::SdrGrafObj(const Graphic
& rGrf
, const Rectangle
& rRect
)
357 : SdrRectObj ( rRect
),
358 pGraphicLink ( NULL
),
361 pGraphic
= new GraphicObject( rGrf
);
362 mpReplacementGraphic
= 0;
363 pGraphic
->SetSwapStreamHdl( LINK( this, SdrGrafObj
, ImpSwapHdl
), SWAPGRAPHIC_TIMEOUT
);
366 // #i118485# Shear allowed and possible now
369 mbGrafAnimationAllowed
= true;
372 mbLineIsOutsideGeometry
= true;
373 mbInsidePaint
= false;
377 mbSupportTextIndentingOnLineWidthChange
= false;
380 SdrGrafObj::SdrGrafObj( const Graphic
& rGrf
)
382 pGraphicLink ( NULL
),
385 pGraphic
= new GraphicObject( rGrf
);
386 mpReplacementGraphic
= 0;
387 pGraphic
->SetSwapStreamHdl( LINK( this, SdrGrafObj
, ImpSwapHdl
), SWAPGRAPHIC_TIMEOUT
);
390 // #i118485# Shear allowed and possible now
393 mbGrafAnimationAllowed
= true;
396 mbLineIsOutsideGeometry
= true;
397 mbInsidePaint
= false;
401 mbSupportTextIndentingOnLineWidthChange
= false;
404 SdrGrafObj::~SdrGrafObj()
407 delete mpReplacementGraphic
;
411 void SdrGrafObj::SetGraphicObject( const GraphicObject
& rGrfObj
)
414 delete mpReplacementGraphic
;
415 mpReplacementGraphic
= 0;
416 pGraphic
->SetSwapStreamHdl( LINK( this, SdrGrafObj
, ImpSwapHdl
), SWAPGRAPHIC_TIMEOUT
);
417 pGraphic
->SetUserData();
420 BroadcastObjectChange();
424 const GraphicObject
& SdrGrafObj::GetGraphicObject(bool bForceSwapIn
) const
434 const GraphicObject
* SdrGrafObj::GetReplacementGraphicObject() const
436 if(!mpReplacementGraphic
&& pGraphic
)
438 const SvgDataPtr
& rSvgDataPtr
= pGraphic
->GetGraphic().getSvgData();
440 if(rSvgDataPtr
.get())
442 const_cast< SdrGrafObj
* >(this)->mpReplacementGraphic
= new GraphicObject(rSvgDataPtr
->getReplacement());
446 return mpReplacementGraphic
;
449 void SdrGrafObj::NbcSetGraphic( const Graphic
& rGrf
)
451 pGraphic
->SetGraphic( rGrf
);
452 delete mpReplacementGraphic
;
453 mpReplacementGraphic
= 0;
454 pGraphic
->SetUserData();
459 void SdrGrafObj::SetGraphic( const Graphic
& rGrf
)
463 BroadcastObjectChange();
466 const Graphic
& SdrGrafObj::GetGraphic() const
469 return pGraphic
->GetGraphic();
472 Graphic
SdrGrafObj::GetTransformedGraphic( sal_uIntPtr nTransformFlags
) const
474 // Refactored most of the code to GraphicObject, where
475 // everybody can use e.g. the cropping functionality
477 GraphicType eType
= GetGraphicType();
478 MapMode
aDestMap( pModel
->GetScaleUnit(), Point(), pModel
->GetScaleFraction(), pModel
->GetScaleFraction() );
479 const Size
aDestSize( GetLogicRect().GetSize() );
480 const bool bMirror
= ( nTransformFlags
& SDRGRAFOBJ_TRANSFORMATTR_MIRROR
) != 0;
481 const bool bRotate
= ( ( nTransformFlags
& SDRGRAFOBJ_TRANSFORMATTR_ROTATE
) != 0 ) &&
482 ( aGeo
.nDrehWink
&& aGeo
.nDrehWink
!= 18000 ) && ( GRAPHIC_NONE
!= eType
);
484 // Need cropping info earlier
485 ( (SdrGrafObj
*) this )->ImpSetAttrToGrafInfo();
486 GraphicAttr aActAttr
;
488 if( SDRGRAFOBJ_TRANSFORMATTR_NONE
!= nTransformFlags
&&
489 GRAPHIC_NONE
!= eType
)
491 // Actually transform the graphic only in this case.
492 // Cropping always happens, though.
493 aActAttr
= aGrafInfo
;
497 sal_uInt16 nMirrorCase
= ( aGeo
.nDrehWink
== 18000 ) ? ( bMirrored
? 3 : 4 ) : ( bMirrored
? 2 : 1 );
498 bool bHMirr
= nMirrorCase
== 2 || nMirrorCase
== 4;
499 bool bVMirr
= nMirrorCase
== 3 || nMirrorCase
== 4;
501 aActAttr
.SetMirrorFlags( ( bHMirr
? BMP_MIRROR_HORZ
: 0 ) | ( bVMirr
? BMP_MIRROR_VERT
: 0 ) );
505 aActAttr
.SetRotation( sal_uInt16(aGeo
.nDrehWink
/ 10) );
508 // Delegate to moved code in GraphicObject
509 return GetGraphicObject().GetTransformedGraphic( aDestSize
, aDestMap
, aActAttr
);
512 GraphicType
SdrGrafObj::GetGraphicType() const
514 return pGraphic
->GetType();
517 bool SdrGrafObj::IsAnimated() const
519 return pGraphic
->IsAnimated();
522 bool SdrGrafObj::IsEPS() const
524 return pGraphic
->IsEPS();
527 bool SdrGrafObj::IsSwappedOut() const
529 return mbIsPreview
? true : pGraphic
->IsSwappedOut();
532 const MapMode
& SdrGrafObj::GetGrafPrefMapMode() const
534 return pGraphic
->GetPrefMapMode();
537 const Size
& SdrGrafObj::GetGrafPrefSize() const
539 return pGraphic
->GetPrefSize();
542 void SdrGrafObj::SetGrafStreamURL( const String
& rGraphicStreamURL
)
545 if( !rGraphicStreamURL
.Len() )
547 pGraphic
->SetUserData();
549 else if( pModel
->IsSwapGraphics() )
551 pGraphic
->SetUserData( rGraphicStreamURL
);
553 // set state of graphic object to 'swapped out'
554 if( pGraphic
->GetType() == GRAPHIC_NONE
)
555 pGraphic
->SetSwapState();
559 String
SdrGrafObj::GetGrafStreamURL() const
561 return pGraphic
->GetUserData();
564 void SdrGrafObj::ForceSwapIn() const
568 // removing preview graphic
569 const String
aUserData( pGraphic
->GetUserData() );
572 pGraphic
->SetGraphic( aEmpty
);
573 pGraphic
->SetUserData( aUserData
);
574 pGraphic
->SetSwapState();
576 const_cast< SdrGrafObj
* >( this )->mbIsPreview
= false;
578 if ( pGraphicLink
&& pGraphic
->IsSwappedOut() )
579 ImpUpdateGraphicLink( false );
581 pGraphic
->FireSwapInRequest();
583 if( pGraphic
->IsSwappedOut() ||
584 ( pGraphic
->GetType() == GRAPHIC_NONE
) ||
585 ( pGraphic
->GetType() == GRAPHIC_DEFAULT
) )
587 Graphic aDefaultGraphic
;
588 aDefaultGraphic
.SetDefaultType();
589 pGraphic
->SetGraphic( aDefaultGraphic
);
593 void SdrGrafObj::ForceSwapOut() const
595 pGraphic
->FireSwapOutRequest();
598 void SdrGrafObj::ImpLinkAnmeldung()
600 sfx2::LinkManager
* pLinkManager
= pModel
!= NULL
? pModel
->GetLinkManager() : NULL
;
602 if( pLinkManager
!= NULL
&& pGraphicLink
== NULL
)
604 if (!aFileName
.isEmpty())
606 pGraphicLink
= new SdrGraphicLink( this );
607 pLinkManager
->InsertFileLink(
608 *pGraphicLink
, OBJECT_CLIENT_GRF
, aFileName
, (aFilterName
.isEmpty() ? NULL
: &aFilterName
), NULL
);
609 pGraphicLink
->Connect();
614 void SdrGrafObj::ImpLinkAbmeldung()
616 sfx2::LinkManager
* pLinkManager
= pModel
!= NULL
? pModel
->GetLinkManager() : NULL
;
618 if( pLinkManager
!= NULL
&& pGraphicLink
!=NULL
)
620 // When using Remove, the *pGraphicLink is implicitly deleted
621 pLinkManager
->Remove( pGraphicLink
);
626 void SdrGrafObj::SetGraphicLink(const OUString
& rFileName
, const String
& rFilterName
)
629 aFileName
= rFileName
;
630 aFilterName
= rFilterName
;
632 pGraphic
->SetUserData();
634 // A linked graphic is per definition swapped out (has to be loaded)
635 pGraphic
->SetSwapState();
638 void SdrGrafObj::ReleaseGraphicLink()
641 aFileName
= OUString();
642 aFilterName
= OUString();
645 bool SdrGrafObj::IsLinkedGraphic() const
647 return !aFileName
.isEmpty();
650 const OUString
& SdrGrafObj::GetFileName() const
655 const OUString
& SdrGrafObj::GetFilterName() const
660 void SdrGrafObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
662 bool bAnim
= pGraphic
->IsAnimated();
663 bool bNoPresGrf
= ( pGraphic
->GetType() != GRAPHIC_NONE
) && !bEmptyPresObj
;
665 rInfo
.bResizeFreeAllowed
= aGeo
.nDrehWink
% 9000 == 0 ||
666 aGeo
.nDrehWink
% 18000 == 0 ||
667 aGeo
.nDrehWink
% 27000 == 0;
669 rInfo
.bResizePropAllowed
= true;
670 rInfo
.bRotateFreeAllowed
= bNoPresGrf
&& !bAnim
;
671 rInfo
.bRotate90Allowed
= bNoPresGrf
&& !bAnim
;
672 rInfo
.bMirrorFreeAllowed
= bNoPresGrf
&& !bAnim
;
673 rInfo
.bMirror45Allowed
= bNoPresGrf
&& !bAnim
;
674 rInfo
.bMirror90Allowed
= !bEmptyPresObj
;
675 rInfo
.bTransparenceAllowed
= false;
676 rInfo
.bGradientAllowed
= false;
678 // #i118485# Shear allowed and possible now
679 rInfo
.bShearAllowed
= true;
681 rInfo
.bEdgeRadiusAllowed
=false;
682 rInfo
.bCanConvToPath
= !IsEPS();
683 rInfo
.bCanConvToPathLineToArea
= false;
684 rInfo
.bCanConvToPolyLineToArea
= false;
685 rInfo
.bCanConvToPoly
= !IsEPS();
686 rInfo
.bCanConvToContour
= (rInfo
.bCanConvToPoly
|| LineGeometryUsageIsNecessary());
689 sal_uInt16
SdrGrafObj::GetObjIdentifier() const
691 return sal_uInt16( OBJ_GRAF
);
694 /* The graphic of the GraphicLink will be loaded. If it is called with
695 bAsynchron = true then the graphic will be set later via DataChanged
697 bool SdrGrafObj::ImpUpdateGraphicLink( bool bAsynchron
) const
703 pGraphicLink
->UpdateAsynchron();
705 pGraphicLink
->DataChanged( ImpLoadLinkedGraphic( aFileName
, aFilterName
) );
711 void SdrGrafObj::ImpSetLinkedGraphic( const Graphic
& rGraphic
)
713 const sal_Bool bIsChanged
= GetModel()->IsChanged();
714 NbcSetGraphic( rGraphic
);
716 BroadcastObjectChange();
717 GetModel()->SetChanged( bIsChanged
);
720 void SdrGrafObj::TakeObjNameSingul(XubString
& rName
) const
724 const SvgDataPtr
& rSvgDataPtr
= pGraphic
->GetGraphic().getSvgData();
726 if(rSvgDataPtr
.get())
728 rName
= ImpGetResStr(STR_ObjNameSingulGRAFSVG
);
732 switch( pGraphic
->GetType() )
736 const sal_uInt16 nId
= ( ( pGraphic
->IsTransparent() || ( (const SdrGrafTransparenceItem
&) GetObjectItem( SDRATTR_GRAFTRANSPARENCE
) ).GetValue() ) ?
737 ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPTRANSLNK
: STR_ObjNameSingulGRAFBMPTRANS
) :
738 ( IsLinkedGraphic() ? STR_ObjNameSingulGRAFBMPLNK
: STR_ObjNameSingulGRAFBMP
) );
740 rName
=ImpGetResStr( nId
);
744 case GRAPHIC_GDIMETAFILE
:
745 rName
=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFMTFLNK
: STR_ObjNameSingulGRAFMTF
);
749 rName
=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFNONELNK
: STR_ObjNameSingulGRAFNONE
);
753 rName
=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNameSingulGRAFLNK
: STR_ObjNameSingulGRAF
);
758 const String
aName(GetName());
762 rName
.AppendAscii( " '" );
764 rName
+= sal_Unicode( '\'' );
769 void SdrGrafObj::TakeObjNamePlural( XubString
& rName
) const
773 const SvgDataPtr
& rSvgDataPtr
= pGraphic
->GetGraphic().getSvgData();
775 if(rSvgDataPtr
.get())
777 rName
= ImpGetResStr(STR_ObjNamePluralGRAFSVG
);
781 switch( pGraphic
->GetType() )
785 const sal_uInt16 nId
= ( ( pGraphic
->IsTransparent() || ( (const SdrGrafTransparenceItem
&) GetObjectItem( SDRATTR_GRAFTRANSPARENCE
) ).GetValue() ) ?
786 ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPTRANSLNK
: STR_ObjNamePluralGRAFBMPTRANS
) :
787 ( IsLinkedGraphic() ? STR_ObjNamePluralGRAFBMPLNK
: STR_ObjNamePluralGRAFBMP
) );
789 rName
=ImpGetResStr( nId
);
793 case GRAPHIC_GDIMETAFILE
:
794 rName
=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFMTFLNK
: STR_ObjNamePluralGRAFMTF
);
798 rName
=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFNONELNK
: STR_ObjNamePluralGRAFNONE
);
802 rName
=ImpGetResStr( IsLinkedGraphic() ? STR_ObjNamePluralGRAFLNK
: STR_ObjNamePluralGRAF
);
807 const String
aName(GetName());
811 rName
.AppendAscii( " '" );
813 rName
+= sal_Unicode( '\'' );
818 SdrObject
* SdrGrafObj::getFullDragClone() const
821 SdrGrafObj
* pRetval
= static_cast< SdrGrafObj
* >(SdrRectObj::getFullDragClone());
823 // #i103116# the full drag clone leads to problems
824 // with linked graphics, so reset the link in this
825 // temporary interaction object and load graphic
826 if(pRetval
&& IsLinkedGraphic())
828 pRetval
->ForceSwapIn();
829 pRetval
->ReleaseGraphicLink();
835 SdrGrafObj
* SdrGrafObj::Clone() const
837 return CloneHelper
< SdrGrafObj
>();
840 SdrGrafObj
& SdrGrafObj::operator=( const SdrGrafObj
& rObj
)
844 SdrRectObj::operator=( rObj
);
846 pGraphic
->SetGraphic( rObj
.GetGraphic(), &rObj
.GetGraphicObject() );
847 aFileName
= rObj
.aFileName
;
848 aFilterName
= rObj
.aFilterName
;
849 bMirrored
= rObj
.bMirrored
;
851 if( rObj
.pGraphicLink
!= NULL
)
853 SetGraphicLink( aFileName
, aFilterName
);
856 ImpSetAttrToGrafInfo();
860 basegfx::B2DPolyPolygon
SdrGrafObj::TakeXorPoly() const
864 basegfx::B2DPolyPolygon aRetval
;
866 // take grown rectangle
867 const sal_Int32
nHalfLineWidth(ImpGetLineWdt() / 2);
868 const Rectangle
aGrownRect(
869 aRect
.Left() - nHalfLineWidth
,
870 aRect
.Top() - nHalfLineWidth
,
871 aRect
.Right() + nHalfLineWidth
,
872 aRect
.Bottom() + nHalfLineWidth
);
874 XPolygon
aXPoly(ImpCalcXPoly(aGrownRect
, GetEckenradius()));
875 aRetval
.append(aXPoly
.getB2DPolygon());
882 return SdrRectObj::TakeXorPoly();
886 sal_uInt32
SdrGrafObj::GetHdlCount() const
891 SdrHdl
* SdrGrafObj::GetHdl(sal_uInt32 nHdlNum
) const
893 return SdrRectObj::GetHdl( nHdlNum
+ 1L );
896 void SdrGrafObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
898 SdrRectObj::NbcResize( rRef
, xFact
, yFact
);
900 bool bMirrX
= xFact
.GetNumerator() < 0;
901 bool bMirrY
= yFact
.GetNumerator() < 0;
903 if( bMirrX
!= bMirrY
)
904 bMirrored
= !bMirrored
;
907 void SdrGrafObj::NbcRotate(const Point
& rRef
, long nWink
, double sn
, double cs
)
909 SdrRectObj::NbcRotate(rRef
,nWink
,sn
,cs
);
912 void SdrGrafObj::NbcMirror(const Point
& rRef1
, const Point
& rRef2
)
914 SdrRectObj::NbcMirror(rRef1
,rRef2
);
915 bMirrored
= !bMirrored
;
918 void SdrGrafObj::NbcShear(const Point
& rRef
, long nWink
, double tn
, bool bVShear
)
920 // #i118485# Call Shear now, old version redirected to rotate
921 SdrRectObj::NbcShear(rRef
, nWink
, tn
, bVShear
);
924 void SdrGrafObj::NbcSetSnapRect(const Rectangle
& rRect
)
926 SdrRectObj::NbcSetSnapRect(rRect
);
929 void SdrGrafObj::NbcSetLogicRect( const Rectangle
& rRect
)
931 SdrRectObj::NbcSetLogicRect(rRect
);
934 SdrObjGeoData
* SdrGrafObj::NewGeoData() const
936 return new SdrGrafObjGeoData
;
939 void SdrGrafObj::SaveGeoData(SdrObjGeoData
& rGeo
) const
941 SdrRectObj::SaveGeoData(rGeo
);
942 SdrGrafObjGeoData
& rGGeo
=(SdrGrafObjGeoData
&)rGeo
;
943 rGGeo
.bMirrored
=bMirrored
;
946 void SdrGrafObj::RestGeoData(const SdrObjGeoData
& rGeo
)
948 SdrRectObj::RestGeoData(rGeo
);
949 SdrGrafObjGeoData
& rGGeo
=(SdrGrafObjGeoData
&)rGeo
;
950 bMirrored
=rGGeo
.bMirrored
;
953 void SdrGrafObj::SetPage( SdrPage
* pNewPage
)
955 bool bRemove
= pNewPage
== NULL
&& pPage
!= NULL
;
956 bool bInsert
= pNewPage
!= NULL
&& pPage
== NULL
;
960 // No SwapIn necessary here, because if something's not loaded, it can't be animated either.
961 if( pGraphic
->IsAnimated())
962 pGraphic
->StopAnimation();
964 if( pGraphicLink
!= NULL
)
968 if(!pModel
&& !GetStyleSheet() && pNewPage
->GetModel())
970 // #i119287# Set default StyleSheet for SdrGrafObj here, it is different from 'Default'. This
971 // needs to be done before the style 'Default' is set from the :SetModel() call which is triggered
972 // from the following :SetPage().
973 // TTTT: Needs to be moved in branch aw080 due to having a SdrModel from the beginning, is at this
974 // place for convenience currently (works in both versions, is not in the way)
975 SfxStyleSheet
* pSheet
= pNewPage
->GetModel()->GetDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj();
979 SetStyleSheet(pSheet
, false);
983 SetMergedItem(XFillStyleItem(XFILL_NONE
));
984 SetMergedItem(XLineStyleItem(XLINE_NONE
));
988 SdrRectObj::SetPage( pNewPage
);
990 if (!aFileName
.isEmpty() && bInsert
)
994 void SdrGrafObj::SetModel( SdrModel
* pNewModel
)
996 bool bChg
= pNewModel
!= pModel
;
1000 if( pGraphic
->HasUserData() )
1003 pGraphic
->SetUserData();
1006 if( pGraphicLink
!= NULL
)
1011 SdrRectObj::SetModel(pNewModel
);
1013 if (bChg
&& !aFileName
.isEmpty())
1017 void SdrGrafObj::StartAnimation( OutputDevice
* /*pOutDev*/, const Point
& /*rPoint*/, const Size
& /*rSize*/, long /*nExtraData*/)
1019 SetGrafAnimationAllowed(true);
1022 bool SdrGrafObj::HasGDIMetaFile() const
1024 return( pGraphic
->GetType() == GRAPHIC_GDIMETAFILE
);
1027 bool SdrGrafObj::isEmbeddedSvg() const
1029 return GRAPHIC_BITMAP
== GetGraphicType() && GetGraphic().getSvgData().get();
1032 GDIMetaFile
SdrGrafObj::getMetafileFromEmbeddedSvg() const
1034 GDIMetaFile aRetval
;
1036 if(isEmbeddedSvg() && GetModel())
1039 const Rectangle
aBoundRect(GetCurrentBoundRect());
1040 const MapMode
aMap(GetModel()->GetScaleUnit(), Point(), GetModel()->GetScaleFraction(), GetModel()->GetScaleFraction());
1042 aOut
.EnableOutput(false);
1043 aOut
.SetMapMode(aMap
);
1044 aRetval
.Record(&aOut
);
1045 SingleObjectPainter(aOut
);
1047 aRetval
.WindStart();
1048 aRetval
.Move(-aBoundRect
.Left(), -aBoundRect
.Top());
1049 aRetval
.SetPrefMapMode(aMap
);
1050 aRetval
.SetPrefSize(aBoundRect
.GetSize());
1056 SdrObject
* SdrGrafObj::DoConvertToPolyObj(sal_Bool bBezier
, bool bAddText
) const
1058 SdrObject
* pRetval
= NULL
;
1059 GraphicType
aGraphicType(GetGraphicType());
1065 // There is currently no helper to create SdrObjects from primitives (even if I'm thinking
1066 // about writing one for some time). To get the roundtrip to SdrObjects it is necessary to
1067 // use the old converter path over the MetaFile mechanism. Create Metafile from Svg
1068 // primitives here pretty directly
1069 aMtf
= getMetafileFromEmbeddedSvg();
1070 aGraphicType
= GRAPHIC_GDIMETAFILE
;
1072 else if(GRAPHIC_GDIMETAFILE
== aGraphicType
)
1074 aMtf
= GetTransformedGraphic(SDRGRAFOBJ_TRANSFORMATTR_COLOR
|SDRGRAFOBJ_TRANSFORMATTR_MIRROR
).GetGDIMetaFile();
1077 switch(aGraphicType
)
1079 case GRAPHIC_GDIMETAFILE
:
1081 // Sort into group and return ONLY those objects that can be created from the MetaFile.
1082 ImpSdrGDIMetaFileImport
aFilter(*GetModel(), GetLayer(), aRect
);
1083 SdrObjGroup
* pGrp
= new SdrObjGroup();
1084 sal_uInt32 nInsAnz
= aFilter
.DoImport(aMtf
, *pGrp
->GetSubList(), 0);
1089 // copy transformation
1090 GeoStat
aGeoStat(GetGeoStat());
1092 if(aGeoStat
.nShearWink
)
1094 aGeoStat
.RecalcTan();
1095 pGrp
->NbcShear(aRect
.TopLeft(), aGeoStat
.nShearWink
, aGeoStat
.nTan
, false);
1098 if(aGeoStat
.nDrehWink
)
1100 aGeoStat
.RecalcSinCos();
1101 pGrp
->NbcRotate(aRect
.TopLeft(), aGeoStat
.nDrehWink
, aGeoStat
.nSin
, aGeoStat
.nCos
);
1106 pGrp
->NbcSetLayer(GetLayer());
1107 pGrp
->SetModel(GetModel());
1111 pRetval
= ImpConvertAddText(pRetval
, bBezier
);
1114 // convert all children
1117 SdrObject
* pHalfDone
= pRetval
;
1118 pRetval
= pHalfDone
->DoConvertToPolyObj(bBezier
, bAddText
);
1119 SdrObject::Free( pHalfDone
); // resulting object is newly created
1123 // flatten subgroups. As we call
1124 // DoConvertToPolyObj() on the resulting group
1125 // objects, subgroups can exist (e.g. text is
1126 // a group object for every line).
1127 SdrObjList
* pList
= pRetval
->GetSubList();
1129 pList
->FlattenGroups();
1138 // #i118485# convert line and fill
1139 SdrObject
* pLineFill
= SdrRectObj::DoConvertToPolyObj(bBezier
, false);
1145 pGrp
= dynamic_cast< SdrObjGroup
* >(pRetval
);
1149 pGrp
= new SdrObjGroup();
1151 pGrp
->NbcSetLayer(GetLayer());
1152 pGrp
->SetModel(GetModel());
1153 pGrp
->GetSubList()->NbcInsertObject(pRetval
);
1156 pGrp
->GetSubList()->NbcInsertObject(pLineFill
, 0);
1160 pRetval
= pLineFill
;
1166 case GRAPHIC_BITMAP
:
1168 // create basic object and add fill
1169 pRetval
= SdrRectObj::DoConvertToPolyObj(bBezier
, bAddText
);
1171 // save bitmap as an attribute
1174 // retrieve bitmap for the fill
1175 SfxItemSet
aSet(GetObjectItemSet());
1177 aSet
.Put(XFillStyleItem(XFILL_BITMAP
));
1178 const BitmapEx
aBitmapEx(GetTransformedGraphic().GetBitmapEx());
1179 aSet
.Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx
)));
1180 aSet
.Put(XFillBmpTileItem(false));
1182 pRetval
->SetMergedItemSet(aSet
);
1187 case GRAPHIC_DEFAULT
:
1189 pRetval
= SdrRectObj::DoConvertToPolyObj(bBezier
, bAddText
);
1197 void SdrGrafObj::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
1200 SdrRectObj::Notify( rBC
, rHint
);
1201 ImpSetAttrToGrafInfo();
1204 bool SdrGrafObj::IsMirrored() const
1209 void SdrGrafObj::SetMirrored( bool _bMirrored
)
1211 bMirrored
= _bMirrored
;
1214 void SdrGrafObj::ImpSetAttrToGrafInfo()
1216 const SfxItemSet
& rSet
= GetObjectItemSet();
1217 const sal_uInt16 nTrans
= ( (SdrGrafTransparenceItem
&) rSet
.Get( SDRATTR_GRAFTRANSPARENCE
) ).GetValue();
1218 const SdrGrafCropItem
& rCrop
= (const SdrGrafCropItem
&) rSet
.Get( SDRATTR_GRAFCROP
);
1220 aGrafInfo
.SetLuminance( ( (SdrGrafLuminanceItem
&) rSet
.Get( SDRATTR_GRAFLUMINANCE
) ).GetValue() );
1221 aGrafInfo
.SetContrast( ( (SdrGrafContrastItem
&) rSet
.Get( SDRATTR_GRAFCONTRAST
) ).GetValue() );
1222 aGrafInfo
.SetChannelR( ( (SdrGrafRedItem
&) rSet
.Get( SDRATTR_GRAFRED
) ).GetValue() );
1223 aGrafInfo
.SetChannelG( ( (SdrGrafGreenItem
&) rSet
.Get( SDRATTR_GRAFGREEN
) ).GetValue() );
1224 aGrafInfo
.SetChannelB( ( (SdrGrafBlueItem
&) rSet
.Get( SDRATTR_GRAFBLUE
) ).GetValue() );
1225 aGrafInfo
.SetGamma( ( (SdrGrafGamma100Item
&) rSet
.Get( SDRATTR_GRAFGAMMA
) ).GetValue() * 0.01 );
1226 aGrafInfo
.SetTransparency( (sal_uInt8
) FRound( std::min( nTrans
, (sal_uInt16
) 100 ) * 2.55 ) );
1227 aGrafInfo
.SetInvert( ( (SdrGrafInvertItem
&) rSet
.Get( SDRATTR_GRAFINVERT
) ).GetValue() );
1228 aGrafInfo
.SetDrawMode( ( (SdrGrafModeItem
&) rSet
.Get( SDRATTR_GRAFMODE
) ).GetValue() );
1229 aGrafInfo
.SetCrop( rCrop
.GetLeft(), rCrop
.GetTop(), rCrop
.GetRight(), rCrop
.GetBottom() );
1235 void SdrGrafObj::AdjustToMaxRect( const Rectangle
& rMaxRect
, bool bShrinkOnly
)
1238 Size
aMaxSize( rMaxRect
.GetSize() );
1239 if ( pGraphic
->GetPrefMapMode().GetMapUnit() == MAP_PIXEL
)
1240 aSize
= Application::GetDefaultDevice()->PixelToLogic( pGraphic
->GetPrefSize(), MAP_100TH_MM
);
1242 aSize
= OutputDevice::LogicToLogic( pGraphic
->GetPrefSize(),
1243 pGraphic
->GetPrefMapMode(),
1244 MapMode( MAP_100TH_MM
) );
1246 if( aSize
.Height() != 0 && aSize
.Width() != 0 )
1248 Point
aPos( rMaxRect
.TopLeft() );
1250 // if the graphic is too large, fit it to page
1251 if ( (!bShrinkOnly
||
1252 ( aSize
.Height() > aMaxSize
.Height() ) ||
1253 ( aSize
.Width() > aMaxSize
.Width() ) )&&
1254 aSize
.Height() && aMaxSize
.Height() )
1256 float fGrfWH
= (float)aSize
.Width() /
1257 (float)aSize
.Height();
1258 float fWinWH
= (float)aMaxSize
.Width() /
1259 (float)aMaxSize
.Height();
1261 // Scale graphic to page size
1262 if ( fGrfWH
< fWinWH
)
1264 aSize
.Width() = (long)(aMaxSize
.Height() * fGrfWH
);
1265 aSize
.Height()= aMaxSize
.Height();
1267 else if ( fGrfWH
> 0.F
)
1269 aSize
.Width() = aMaxSize
.Width();
1270 aSize
.Height()= (long)(aMaxSize
.Width() / fGrfWH
);
1273 aPos
= rMaxRect
.Center();
1277 aPos
= aRect
.TopLeft();
1279 aPos
.X() -= aSize
.Width() / 2;
1280 aPos
.Y() -= aSize
.Height() / 2;
1281 SetLogicRect( Rectangle( aPos
, aSize
) );
1285 IMPL_LINK( SdrGrafObj
, ImpSwapHdl
, GraphicObject
*, pO
)
1287 SvStream
* pRet
= GRFMGR_AUTOSWAPSTREAM_NONE
;
1289 if( pO
->IsInSwapOut() )
1291 if( pModel
&& !mbIsPreview
&& pModel
->IsSwapGraphics() && pGraphic
->GetSizeBytes() > 20480 )
1293 // test if this object is visualized from someone
1294 // ## test only if there are VOCs other than the preview renderer
1295 if(!GetViewContact().HasViewObjectContacts(true))
1297 const sal_uIntPtr nSwapMode
= pModel
->GetSwapGraphicsMode();
1299 if( ( pGraphic
->HasUserData() || pGraphicLink
) &&
1300 ( nSwapMode
& SDR_SWAPGRAPHICSMODE_PURGE
) )
1302 pRet
= GRFMGR_AUTOSWAPSTREAM_LINK
;
1304 else if( nSwapMode
& SDR_SWAPGRAPHICSMODE_TEMP
)
1306 pRet
= GRFMGR_AUTOSWAPSTREAM_TEMP
;
1307 pGraphic
->SetUserData();
1311 sdr::contact::ViewContactOfGraphic
* pVC
= dynamic_cast< sdr::contact::ViewContactOfGraphic
* >(&GetViewContact());
1315 pVC
->flushGraphicObjects();
1320 else if( pO
->IsInSwapIn() )
1322 // can be loaded from the original document stream later
1323 if( pModel
!= NULL
)
1325 if( pGraphic
->HasUserData() )
1327 ::comphelper::LifecycleProxy proxy
;
1328 OUString aUserData
= pGraphic
->GetUserData();
1329 uno::Reference
<io::XInputStream
> const xStream(
1330 pModel
->GetDocumentStream(aUserData
, proxy
));
1332 ::boost::scoped_ptr
<SvStream
> const pStream( (xStream
.is())
1333 ? ::utl::UcbStreamHelper::CreateStream(xStream
)
1336 if( pStream
!= NULL
)
1340 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
>* pFilterData
= NULL
;
1342 if(mbInsidePaint
&& !GetViewContact().HasViewObjectContacts(true))
1344 pFilterData
= new com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
>( 3 );
1346 com::sun::star::awt::Size
aPreviewSizeHint( 64, 64 );
1347 sal_Bool bAllowPartialStreamRead
= true;
1348 sal_Bool bCreateNativeLink
= false;
1349 (*pFilterData
)[ 0 ].Name
= String( RTL_CONSTASCII_USTRINGPARAM( "PreviewSizeHint" ) );
1350 (*pFilterData
)[ 0 ].Value
<<= aPreviewSizeHint
;
1351 (*pFilterData
)[ 1 ].Name
= String( RTL_CONSTASCII_USTRINGPARAM( "AllowPartialStreamRead" ) );
1352 (*pFilterData
)[ 1 ].Value
<<= bAllowPartialStreamRead
;
1353 (*pFilterData
)[ 2 ].Name
= String( RTL_CONSTASCII_USTRINGPARAM( "CreateNativeLink" ) );
1354 (*pFilterData
)[ 2 ].Value
<<= bCreateNativeLink
;
1359 if(!GraphicFilter::GetGraphicFilter().ImportGraphic(
1360 aGraphic
, aUserData
, *pStream
,
1361 GRFILTER_FORMAT_DONTKNOW
, NULL
, 0, pFilterData
))
1363 const String
aNewUserData( pGraphic
->GetUserData() );
1365 pGraphic
->SetGraphic( aGraphic
);
1366 pGraphic
->SetUserData( aNewUserData
);
1368 // Graphic successfully swapped in.
1369 pRet
= GRFMGR_AUTOSWAPSTREAM_LOADED
;
1373 pStream
->ResetError();
1376 else if( !ImpUpdateGraphicLink( false ) )
1378 pRet
= GRFMGR_AUTOSWAPSTREAM_TEMP
;
1382 pRet
= GRFMGR_AUTOSWAPSTREAM_LOADED
;
1386 pRet
= GRFMGR_AUTOSWAPSTREAM_TEMP
;
1389 return (long)(void*) pRet
;
1392 void SdrGrafObj::SetGrafAnimationAllowed(bool bNew
)
1394 if(mbGrafAnimationAllowed
!= bNew
)
1396 mbGrafAnimationAllowed
= bNew
;
1401 Reference
< XInputStream
> SdrGrafObj::getInputStream()
1403 Reference
< XInputStream
> xStream
;
1407 // can be loaded from the original document stream later
1408 if( pGraphic
->HasUserData() )
1410 ::comphelper::LifecycleProxy proxy
;
1412 pModel
->GetDocumentStream(pGraphic
->GetUserData(), proxy
));
1413 // fdo#46340: this may look completely insane, and it is,
1414 // but it also prevents a crash: the LifecycleProxy will go out
1415 // of scope, but the xStream must be returned; the UcbStreamHelper
1416 // will actually copy the xStream to a temp file (because it is
1417 // not seekable), which makes it not crash...
1418 SvStream
*const pStream
=
1419 utl::UcbStreamHelper::CreateStream(xStream
);
1420 xStream
.set(new utl::OInputStreamWrapper(pStream
, true));
1422 else if( pGraphic
&& GetGraphic().IsLink() )
1424 Graphic
aGraphic( GetGraphic() );
1425 GfxLink
aLink( aGraphic
.GetLink() );
1426 sal_uInt32 nSize
= aLink
.GetDataSize();
1427 const void* pSourceData
= (const void*)aLink
.GetData();
1428 if( nSize
&& pSourceData
)
1430 sal_uInt8
* pBuffer
= new sal_uInt8
[ nSize
];
1433 memcpy( pBuffer
, pSourceData
, nSize
);
1435 SvMemoryStream
* pStream
= new SvMemoryStream( (void*)pBuffer
, (sal_Size
)nSize
, STREAM_READ
);
1436 pStream
->ObjectOwnsMemory( true );
1437 xStream
.set( new utl::OInputStreamWrapper( pStream
, true ) );
1442 if (!xStream
.is() && !aFileName
.isEmpty())
1444 SvFileStream
* pStream
= new SvFileStream( aFileName
, STREAM_READ
);
1446 xStream
.set( new utl::OInputStreamWrapper( pStream
) );
1453 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */