xref: /trunk/main/svtools/source/misc/embedhlp.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #include <svtools/embedhlp.hxx>
32 #include <svtools/filter.hxx>
33 #include <svtools/svtools.hrc>
34 #include <svtools/svtdata.hxx>
35 
36 #include <comphelper/embeddedobjectcontainer.hxx>
37 #include <comphelper/seqstream.hxx>
38 #include <toolkit/helper/vclunohelper.hxx>
39 #include <unotools/ucbstreamhelper.hxx>
40 #include <unotools/streamwrap.hxx>
41 
42 #include <tools/globname.hxx>
43 #include <sot/clsids.hxx>
44 #include <com/sun/star/util/XModifyListener.hpp>
45 #ifndef _COM_SUN_STAR_UTIL_XMODIFYiBLE_HPP_
46 #include <com/sun/star/util/XModifiable.hpp>
47 #endif
48 #include <com/sun/star/embed/EmbedStates.hpp>
49 #include <com/sun/star/embed/EmbedMisc.hpp>
50 #include <com/sun/star/embed/XStateChangeListener.hpp>
51 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
52 #include <com/sun/star/util/XModifiable.hpp>
53 #include <com/sun/star/datatransfer/XTransferable.hpp>
54 #include <com/sun/star/chart2/XDefaultSizeTransmitter.hpp>
55 #include <cppuhelper/implbase4.hxx>
56 #include "vcl/svapp.hxx"
57 #include <rtl/logfile.hxx>
58 #include <vos/mutex.hxx>
59 
60 using namespace com::sun::star;
61 
62 namespace svt
63 {
64 
65 class EmbedEventListener_Impl : public ::cppu::WeakImplHelper4 < embed::XStateChangeListener,
66                                                                  document::XEventListener,
67                                                                  util::XModifyListener,
68                                                                  util::XCloseListener >
69 {
70 public:
71     EmbeddedObjectRef*          pObject;
72     sal_Int32                   nState;
73 
74                                 EmbedEventListener_Impl( EmbeddedObjectRef* p ) :
75                                     pObject(p)
76                                     , nState(-1)
77                                 {}
78 
79     static EmbedEventListener_Impl* Create( EmbeddedObjectRef* );
80 
81     virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
82                                     throw (embed::WrongStateException, uno::RuntimeException);
83     virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
84                                     throw (uno::RuntimeException);
85     virtual void SAL_CALL queryClosing( const lang::EventObject& Source, ::sal_Bool GetsOwnership )
86                                     throw (util::CloseVetoException, uno::RuntimeException);
87     virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException);
88     virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException );
89     virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException );
90     virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
91 };
92 
93 EmbedEventListener_Impl* EmbedEventListener_Impl::Create( EmbeddedObjectRef* p )
94 {
95     EmbedEventListener_Impl* xRet = new EmbedEventListener_Impl( p );
96     xRet->acquire();
97 
98     if ( p->GetObject().is() )
99     {
100         p->GetObject()->addStateChangeListener( xRet );
101 
102         uno::Reference < util::XCloseable > xClose( p->GetObject(), uno::UNO_QUERY );
103         DBG_ASSERT( xClose.is(), "Object does not support XCloseable!" );
104         if ( xClose.is() )
105             xClose->addCloseListener( xRet );
106 
107         uno::Reference < document::XEventBroadcaster > xBrd( p->GetObject(), uno::UNO_QUERY );
108         if ( xBrd.is() )
109             xBrd->addEventListener( xRet );
110 
111         xRet->nState = p->GetObject()->getCurrentState();
112         if ( xRet->nState == embed::EmbedStates::RUNNING )
113         {
114             uno::Reference < util::XModifiable > xMod( p->GetObject()->getComponent(), uno::UNO_QUERY );
115             if ( xMod.is() )
116                 // listen for changes in running state (update replacements in case of changes)
117                 xMod->addModifyListener( xRet );
118         }
119     }
120 
121     return xRet;
122 }
123 
124 void SAL_CALL EmbedEventListener_Impl::changingState( const lang::EventObject&,
125                                                     ::sal_Int32,
126                                                     ::sal_Int32 )
127     throw ( embed::WrongStateException,
128             uno::RuntimeException )
129 {
130 }
131 
132 void SAL_CALL EmbedEventListener_Impl::stateChanged( const lang::EventObject&,
133                                                     ::sal_Int32 nOldState,
134                                                     ::sal_Int32 nNewState )
135     throw ( uno::RuntimeException )
136 {
137     ::vos::OGuard aGuard( Application::GetSolarMutex() );
138     nState = nNewState;
139     if ( !pObject )
140         return;
141 
142     uno::Reference < util::XModifiable > xMod( pObject->GetObject()->getComponent(), uno::UNO_QUERY );
143     if ( nNewState == embed::EmbedStates::RUNNING )
144     {
145         // TODO/LATER: container must be set before!
146         // When is this event created? Who sets the new container when it changed?
147         if( ( pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON ) && nOldState != embed::EmbedStates::LOADED && !pObject->IsChart() )
148             // get new replacement after deactivation
149             pObject->UpdateReplacement();
150 
151         if( pObject->IsChart() && nOldState == embed::EmbedStates::UI_ACTIVE )
152         {
153             //create a new metafile replacement when leaving the edit mode
154             //for buggy documents where the old image looks different from the correct one
155             if( xMod.is() && !xMod->isModified() )//in case of modification a new replacement will be requested anyhow
156                 pObject->UpdateReplacementOnDemand();
157         }
158 
159         if ( xMod.is() && nOldState == embed::EmbedStates::LOADED )
160             // listen for changes (update replacements in case of changes)
161             xMod->addModifyListener( this );
162     }
163     else if ( nNewState == embed::EmbedStates::LOADED )
164     {
165         // in loaded state we can't listen
166         if ( xMod.is() )
167             xMod->removeModifyListener( this );
168     }
169 }
170 
171 void SAL_CALL EmbedEventListener_Impl::modified( const lang::EventObject& ) throw (uno::RuntimeException)
172 {
173     ::vos::OGuard aGuard( Application::GetSolarMutex() );
174     if ( pObject && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON )
175     {
176         if ( nState == embed::EmbedStates::RUNNING )
177         {
178             // updates only necessary in non-active states
179             if( pObject->IsChart() )
180                 pObject->UpdateReplacementOnDemand();
181             else
182                 pObject->UpdateReplacement();
183         }
184         else if ( nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::INPLACE_ACTIVE )
185         {
186             // in case the object is inplace or UI active the replacement image should be updated on demand
187             pObject->UpdateReplacementOnDemand();
188         }
189     }
190 }
191 
192 void SAL_CALL EmbedEventListener_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException )
193 {
194     ::vos::OGuard aGuard( Application::GetSolarMutex() );
195 
196 #if 0
197     if ( pObject && aEvent.EventName.equalsAscii("OnSaveDone") || aEvent.EventName.equalsAscii("OnSaveAsDone") )
198     {
199         // TODO/LATER: container must be set before!
200         // When is this event created? Who sets the new container when it changed?
201         pObject->UpdateReplacement();
202     }
203     else
204 #endif
205     if ( pObject && aEvent.EventName.equalsAscii("OnVisAreaChanged") && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON && !pObject->IsChart() )
206     {
207         pObject->UpdateReplacement();
208     }
209 }
210 
211 void SAL_CALL EmbedEventListener_Impl::queryClosing( const lang::EventObject& Source, ::sal_Bool )
212         throw ( util::CloseVetoException, uno::RuntimeException)
213 {
214     // An embedded object can be shared between several objects (f.e. for undo purposes)
215     // the object will not be closed before the last "customer" is destroyed
216     // Now the EmbeddedObjectRef helper class works like a "lock" on the object
217     if ( pObject && pObject->IsLocked() && Source.Source == pObject->GetObject() )
218         throw util::CloseVetoException();
219 }
220 
221 void SAL_CALL EmbedEventListener_Impl::notifyClosing( const lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException)
222 {
223     if ( pObject && Source.Source == pObject->GetObject() )
224     {
225         pObject->Clear();
226         pObject = 0;
227     }
228 }
229 
230 void SAL_CALL EmbedEventListener_Impl::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException )
231 {
232     if ( pObject && aEvent.Source == pObject->GetObject() )
233     {
234         pObject->Clear();
235         pObject = 0;
236     }
237 }
238 
239 struct EmbeddedObjectRef_Impl
240 {
241     EmbedEventListener_Impl*                    xListener;
242     ::rtl::OUString                             aPersistName;
243     ::rtl::OUString                             aMediaType;
244     comphelper::EmbeddedObjectContainer*        pContainer;
245     Graphic*                                    pGraphic;
246     Graphic*                                    pHCGraphic;
247     sal_Int64                                   nViewAspect;
248     sal_Bool                                        bIsLocked;
249     sal_Bool                                    bNeedUpdate;
250 
251     // #i104867#
252     sal_uInt32                                  mnGraphicVersion;
253     awt::Size                                   aDefaultSizeForChart_In_100TH_MM;//#i103460# charts do not necessaryly have an own size within ODF files, in this case they need to use the size settings from the surrounding frame, which is made available with this member
254 };
255 
256 void EmbeddedObjectRef::Construct_Impl()
257 {
258     mpImp = new EmbeddedObjectRef_Impl;
259     mpImp->pContainer = 0;
260     mpImp->pGraphic = 0;
261     mpImp->pHCGraphic = 0;
262     mpImp->nViewAspect = embed::Aspects::MSOLE_CONTENT;
263     mpImp->bIsLocked = sal_False;
264     mpImp->bNeedUpdate = sal_False;
265     mpImp->mnGraphicVersion = 0;
266     mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size(8000,7000);
267 }
268 
269 EmbeddedObjectRef::EmbeddedObjectRef()
270 {
271     Construct_Impl();
272 }
273 
274 EmbeddedObjectRef::EmbeddedObjectRef( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect )
275 {
276     Construct_Impl();
277     mpImp->nViewAspect = nAspect;
278     mxObj = xObj;
279     mpImp->xListener = EmbedEventListener_Impl::Create( this );
280 }
281 
282 EmbeddedObjectRef::EmbeddedObjectRef( const EmbeddedObjectRef& rObj )
283 {
284     mpImp = new EmbeddedObjectRef_Impl;
285     mpImp->pContainer = rObj.mpImp->pContainer;
286     mpImp->nViewAspect = rObj.mpImp->nViewAspect;
287     mpImp->bIsLocked = rObj.mpImp->bIsLocked;
288     mxObj = rObj.mxObj;
289     mpImp->xListener = EmbedEventListener_Impl::Create( this );
290     mpImp->aPersistName = rObj.mpImp->aPersistName;
291     mpImp->aMediaType = rObj.mpImp->aMediaType;
292     mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate;
293     mpImp->aDefaultSizeForChart_In_100TH_MM = rObj.mpImp->aDefaultSizeForChart_In_100TH_MM;
294 
295     if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate )
296         mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic );
297     else
298         mpImp->pGraphic = 0;
299 
300     mpImp->pHCGraphic = 0;
301     mpImp->mnGraphicVersion = 0;
302 }
303 
304 EmbeddedObjectRef::~EmbeddedObjectRef()
305 {
306     delete mpImp->pGraphic;
307     if ( mpImp->pHCGraphic )
308         DELETEZ( mpImp->pHCGraphic );
309     Clear();
310 }
311 /*
312 EmbeddedObjectRef& EmbeddedObjectRef::operator = ( const EmbeddedObjectRef& rObj )
313 {
314     DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" );
315 
316     delete mpImp->pGraphic;
317     if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic );
318     Clear();
319 
320     mpImp->nViewAspect = rObj.mpImp->nViewAspect;
321     mpImp->bIsLocked = rObj.mpImp->bIsLocked;
322     mxObj = rObj.mxObj;
323     mpImp->xListener = EmbedEventListener_Impl::Create( this );
324     mpImp->pContainer = rObj.mpImp->pContainer;
325     mpImp->aPersistName = rObj.mpImp->aPersistName;
326     mpImp->aMediaType = rObj.mpImp->aMediaType;
327     mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate;
328 
329     if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate )
330         mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic );
331     else
332         mpImp->pGraphic = 0;
333     return *this;
334 }
335 */
336 void EmbeddedObjectRef::Assign( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect )
337 {
338     DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" );
339 
340     Clear();
341     mpImp->nViewAspect = nAspect;
342     mxObj = xObj;
343     mpImp->xListener = EmbedEventListener_Impl::Create( this );
344 
345     //#i103460#
346     if ( IsChart() )
347     {
348         ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( xObj, uno::UNO_QUERY );
349         DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
350         if( xSizeTransmitter.is() )
351             xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM );
352     }
353 }
354 
355 void EmbeddedObjectRef::Clear()
356 {
357     if ( mxObj.is() && mpImp->xListener )
358     {
359         mxObj->removeStateChangeListener( mpImp->xListener );
360 
361         uno::Reference < util::XCloseable > xClose( mxObj, uno::UNO_QUERY );
362         if ( xClose.is() )
363             xClose->removeCloseListener( mpImp->xListener );
364 
365         uno::Reference < document::XEventBroadcaster > xBrd( mxObj, uno::UNO_QUERY );
366         if ( xBrd.is() )
367             xBrd->removeEventListener( mpImp->xListener );
368 
369         if ( mpImp->bIsLocked )
370         {
371             if ( xClose.is() )
372             {
373                 try
374                 {
375                     mxObj->changeState( embed::EmbedStates::LOADED );
376                     xClose->close( sal_True );
377                 }
378                 catch ( util::CloseVetoException& )
379                 {
380                     // there's still someone who needs the object!
381                 }
382                 catch ( uno::Exception& )
383                 {
384                     OSL_ENSURE( sal_False, "Error on switching of the object to loaded state and closing!\n" );
385                 }
386             }
387         }
388 
389         if ( mpImp->xListener )
390         {
391             mpImp->xListener->pObject = 0;
392             mpImp->xListener->release();
393             mpImp->xListener = 0;
394         }
395 
396         mxObj = 0;
397         mpImp->bNeedUpdate = sal_False;
398     }
399 
400     mpImp->pContainer = 0;
401     mpImp->bIsLocked = sal_False;
402     mpImp->bNeedUpdate = sal_False;
403 }
404 
405 void EmbeddedObjectRef::AssignToContainer( comphelper::EmbeddedObjectContainer* pContainer, const ::rtl::OUString& rPersistName )
406 {
407     mpImp->pContainer = pContainer;
408     mpImp->aPersistName = rPersistName;
409 
410     if ( mpImp->pGraphic && !mpImp->bNeedUpdate && pContainer )
411         SetGraphicToContainer( *mpImp->pGraphic, *pContainer, mpImp->aPersistName, ::rtl::OUString() );
412 }
413 
414 comphelper::EmbeddedObjectContainer* EmbeddedObjectRef::GetContainer() const
415 {
416     return mpImp->pContainer;
417 }
418 
419 ::rtl::OUString EmbeddedObjectRef::GetPersistName() const
420 {
421     return mpImp->aPersistName;
422 }
423 
424 MapUnit EmbeddedObjectRef::GetMapUnit() const
425 {
426     if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT )
427         return VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) );
428     else
429         // TODO/LATER: currently only CONTENT aspect requires communication with the object
430         return MAP_100TH_MM;
431 }
432 
433 sal_Int64 EmbeddedObjectRef::GetViewAspect() const
434 {
435     return mpImp->nViewAspect;
436 }
437 
438 void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect )
439 {
440     mpImp->nViewAspect = nAspect;
441 }
442 
443 void EmbeddedObjectRef::Lock( sal_Bool bLock )
444 {
445     mpImp->bIsLocked = bLock;
446 }
447 
448 sal_Bool EmbeddedObjectRef::IsLocked() const
449 {
450     return mpImp->bIsLocked;
451 }
452 
453 void EmbeddedObjectRef::GetReplacement( sal_Bool bUpdate )
454 {
455     if ( bUpdate )
456     {
457         DELETEZ( mpImp->pGraphic );
458         mpImp->aMediaType = ::rtl::OUString();
459         mpImp->pGraphic = new Graphic;
460         if ( mpImp->pHCGraphic )
461             DELETEZ( mpImp->pHCGraphic );
462         mpImp->mnGraphicVersion++;
463     }
464     else if ( !mpImp->pGraphic )
465     {
466         mpImp->pGraphic = new Graphic;
467         mpImp->mnGraphicVersion++;
468     }
469     else
470     {
471         DBG_ERROR("No update, but replacement exists already!");
472         return;
473     }
474 
475     SvStream* pGraphicStream = GetGraphicStream( bUpdate );
476     if ( pGraphicStream )
477     {
478         GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
479         if( mpImp->pGraphic )
480             pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
481         mpImp->mnGraphicVersion++;
482         delete pGraphicStream;
483     }
484 }
485 
486 Graphic* EmbeddedObjectRef::GetGraphic( ::rtl::OUString* pMediaType ) const
487 {
488     if ( mpImp->bNeedUpdate )
489         // bNeedUpdate will be set to false while retrieving new replacement
490         const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_True );
491     else if ( !mpImp->pGraphic )
492         const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_False );
493 
494     if ( mpImp->pGraphic && pMediaType )
495         *pMediaType = mpImp->aMediaType;
496     return mpImp->pGraphic;
497 }
498 
499 Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const
500 {
501     MapMode aSourceMapMode( MAP_100TH_MM );
502     Size aResult;
503 
504     if ( mpImp->nViewAspect == embed::Aspects::MSOLE_ICON )
505     {
506         Graphic* pGraphic = GetGraphic();
507         if ( pGraphic )
508         {
509             aSourceMapMode = pGraphic->GetPrefMapMode();
510             aResult = pGraphic->GetPrefSize();
511         }
512         else
513             aResult = Size( 2500, 2500 );
514     }
515     else
516     {
517         awt::Size aSize;
518 
519         if ( mxObj.is() )
520         {
521             try
522             {
523                 aSize = mxObj->getVisualAreaSize( mpImp->nViewAspect );
524             }
525             catch( embed::NoVisualAreaSizeException& )
526             {
527             }
528             catch( uno::Exception& )
529             {
530                 OSL_ENSURE( sal_False, "Something went wrong on getting of the size of the object!" );
531             }
532 
533             try
534             {
535                 aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) );
536             }
537             catch( uno::Exception )
538             {
539                 OSL_ENSURE( sal_False, "Can not get the map mode!" );
540             }
541         }
542 
543         if ( !aSize.Height && !aSize.Width )
544         {
545             aSize.Width = 5000;
546             aSize.Height = 5000;
547         }
548 
549         aResult = Size( aSize.Width, aSize.Height );
550     }
551 
552     if ( pTargetMapMode )
553         aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode );
554 
555     return aResult;
556 }
557 
558 Graphic* EmbeddedObjectRef::GetHCGraphic() const
559 {
560     if ( !mpImp->pHCGraphic )
561     {
562         uno::Reference< io::XInputStream > xInStream;
563         try
564         {
565             // if the object needs size on load, that means that it is not our object
566             // currently the HC mode is supported only for OOo own objects so the following
567             // check is used as an optimization
568             // TODO/LATER: shouldn't there be a special status flag to detect alien implementation?
569             if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT
570               && mxObj.is() && !( mxObj->getStatus( mpImp->nViewAspect ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD ) )
571             {
572                 // TODO/LATER: optimization, it makes no sence to do it for OLE objects
573                 if ( mxObj->getCurrentState() == embed::EmbedStates::LOADED )
574                     mxObj->changeState( embed::EmbedStates::RUNNING );
575 
576                 // TODO: return for the aspect of the document
577                 embed::VisualRepresentation aVisualRepresentation;
578                 uno::Reference< datatransfer::XTransferable > xTransferable( mxObj->getComponent(), uno::UNO_QUERY );
579                 if ( !xTransferable.is() )
580                     throw uno::RuntimeException();
581 
582                 datatransfer::DataFlavor aDataFlavor(
583                         ::rtl::OUString::createFromAscii(
584                                 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" ),
585                         ::rtl::OUString::createFromAscii( "GDIMetaFile" ),
586                         ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
587 
588                 uno::Sequence < sal_Int8 > aSeq;
589                 if ( ( xTransferable->getTransferData( aDataFlavor ) >>= aSeq ) && aSeq.getLength() )
590                     xInStream = new ::comphelper::SequenceInputStream( aSeq );
591             }
592         }
593         catch ( uno::Exception& )
594         {
595         }
596 
597         if ( xInStream.is() )
598         {
599             SvStream* pStream = NULL;
600             pStream = ::utl::UcbStreamHelper::CreateStream( xInStream );
601             if ( pStream )
602             {
603                 if ( !pStream->GetError() )
604                 {
605                     GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
606                     Graphic* pGraphic = new Graphic();
607                     if ( pGF->ImportGraphic( *pGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW ) == 0 )
608                         mpImp->pHCGraphic = pGraphic;
609                     else
610                         delete pGraphic;
611                     mpImp->mnGraphicVersion++;
612                 }
613 
614                 delete pStream;
615             }
616         }
617     }
618 
619     return mpImp->pHCGraphic;
620 }
621 
622 void EmbeddedObjectRef::SetGraphicStream( const uno::Reference< io::XInputStream >& xInGrStream,
623                                             const ::rtl::OUString& rMediaType )
624 {
625     if ( mpImp->pGraphic )
626         delete mpImp->pGraphic;
627     mpImp->pGraphic = new Graphic();
628     mpImp->aMediaType = rMediaType;
629     if ( mpImp->pHCGraphic )
630         DELETEZ( mpImp->pHCGraphic );
631     mpImp->mnGraphicVersion++;
632 
633     SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( xInGrStream );
634 
635     if ( pGraphicStream )
636     {
637         GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
638         pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
639         mpImp->mnGraphicVersion++;
640 
641         if ( mpImp->pContainer )
642         {
643             pGraphicStream->Seek( 0 );
644             uno::Reference< io::XInputStream > xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream );
645 
646             mpImp->pContainer->InsertGraphicStream( xInSeekGrStream, mpImp->aPersistName, rMediaType );
647         }
648 
649         delete pGraphicStream;
650     }
651 
652     mpImp->bNeedUpdate = sal_False;
653 
654 }
655 
656 void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const ::rtl::OUString& rMediaType )
657 {
658     if ( mpImp->pGraphic )
659         delete mpImp->pGraphic;
660     mpImp->pGraphic = new Graphic( rGraphic );
661     mpImp->aMediaType = rMediaType;
662     if ( mpImp->pHCGraphic )
663         DELETEZ( mpImp->pHCGraphic );
664     mpImp->mnGraphicVersion++;
665 
666     if ( mpImp->pContainer )
667         SetGraphicToContainer( rGraphic, *mpImp->pContainer, mpImp->aPersistName, rMediaType );
668 
669     mpImp->bNeedUpdate = sal_False;
670 }
671 
672 SvStream* EmbeddedObjectRef::GetGraphicStream( sal_Bool bUpdate ) const
673 {
674     RTL_LOGFILE_CONTEXT( aLog, "svtools (mv76033) svt::EmbeddedObjectRef::GetGraphicStream" );
675     DBG_ASSERT( bUpdate || mpImp->pContainer, "Can't retrieve current graphic!" );
676     uno::Reference < io::XInputStream > xStream;
677     if ( mpImp->pContainer && !bUpdate )
678     {
679         RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from container" );
680         // try to get graphic stream from container storage
681         xStream = mpImp->pContainer->GetGraphicStream( mxObj, &mpImp->aMediaType );
682         if ( xStream.is() )
683         {
684             const sal_Int32 nConstBufferSize = 32000;
685             SvStream *pStream = new SvMemoryStream( 32000, 32000 );
686             sal_Int32 nRead=0;
687             uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
688             do
689             {
690                 nRead = xStream->readBytes ( aSequence, nConstBufferSize );
691                 pStream->Write( aSequence.getConstArray(), nRead );
692             }
693             while ( nRead == nConstBufferSize );
694             pStream->Seek(0);
695             return pStream;
696         }
697     }
698 
699     if ( !xStream.is() )
700     {
701         RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from object" );
702         // update wanted or no stream in container storage available
703         xStream = GetGraphicReplacementStream( mpImp->nViewAspect, mxObj, &mpImp->aMediaType );
704 
705         if ( xStream.is() )
706         {
707             if ( mpImp->pContainer )
708                 mpImp->pContainer->InsertGraphicStream( xStream, mpImp->aPersistName, mpImp->aMediaType );
709 
710             SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream );
711             if ( pResult && bUpdate )
712                 mpImp->bNeedUpdate = sal_False;
713 
714             return pResult;
715         }
716     }
717 
718     return NULL;
719 }
720 
721 void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const String &rText, OutputDevice *pOut )
722 {
723     MapMode aMM( MAP_APPFONT );
724     Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL );
725     Font aFnt( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Helvetica" ) ), aAppFontSz );
726     aFnt.SetTransparent( sal_True );
727     aFnt.SetColor( Color( COL_LIGHTRED ) );
728     aFnt.SetWeight( WEIGHT_BOLD );
729     aFnt.SetFamily( FAMILY_SWISS );
730 
731     pOut->Push();
732     pOut->SetBackground();
733     pOut->SetFont( aFnt );
734 
735     Point aPt;
736     // Nun den Text so skalieren, dass er in das Rect passt.
737     // Wir fangen mit der Defaultsize an und gehen 1-AppFont runter
738     for( sal_uInt16 i = 8; i > 2; i-- )
739     {
740         aPt.X() = (rRect.GetWidth()  - pOut->GetTextWidth( rText )) / 2;
741         aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2;
742 
743         sal_Bool bTiny = sal_False;
744         if( aPt.X() < 0 ) bTiny = sal_True, aPt.X() = 0;
745         if( aPt.Y() < 0 ) bTiny = sal_True, aPt.Y() = 0;
746         if( bTiny )
747         {
748             // heruntergehen bei kleinen Bildern
749             aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) );
750             pOut->SetFont( aFnt );
751         }
752         else
753             break;
754     }
755 
756     Bitmap aBmp( SvtResId( BMP_PLUGIN ) );
757     long nHeight = rRect.GetHeight() - pOut->GetTextHeight();
758     long nWidth = rRect.GetWidth();
759     if( nHeight > 0 )
760     {
761         aPt.Y() = nHeight;
762         Point   aP = rRect.TopLeft();
763         Size    aBmpSize = aBmp.GetSizePixel();
764         // Bitmap einpassen
765         if( nHeight * 10 / nWidth
766           > aBmpSize.Height() * 10 / aBmpSize.Width() )
767         {
768             // nach der Breite ausrichten
769             // Proportion beibehalten
770             long nH = nWidth * aBmpSize.Height() / aBmpSize.Width();
771             // zentrieren
772             aP.Y() += (nHeight - nH) / 2;
773             nHeight = nH;
774         }
775         else
776         {
777             // nach der H"ohe ausrichten
778             // Proportion beibehalten
779             long nW = nHeight * aBmpSize.Width() / aBmpSize.Height();
780             // zentrieren
781             aP.X() += (nWidth - nW) / 2;
782             nWidth = nW;
783         }
784 
785         pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp );
786     }
787 
788     pOut->IntersectClipRegion( rRect );
789     aPt += rRect.TopLeft();
790     pOut->DrawText( aPt, rText );
791     pOut->Pop();
792 }
793 
794 void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut )
795 {
796     GDIMetaFile * pMtf = pOut->GetConnectMetaFile();
797     if( pMtf && pMtf->IsRecord() )
798         return;
799 
800     pOut->Push();
801     pOut->SetLineColor( Color( COL_BLACK ) );
802 
803     Size aPixSize = pOut->LogicToPixel( rRect.GetSize() );
804     aPixSize.Width() -= 1;
805     aPixSize.Height() -= 1;
806     Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() );
807     sal_Int32 nMax = aPixSize.Width() + aPixSize.Height();
808     for( sal_Int32 i = 5; i < nMax; i += 5 )
809     {
810         Point a1( aPixViewPos ), a2( aPixViewPos );
811         if( i > aPixSize.Width() )
812             a1 += Point( aPixSize.Width(), i - aPixSize.Width() );
813         else
814             a1 += Point( i, 0 );
815         if( i > aPixSize.Height() )
816             a2 += Point( i - aPixSize.Height(), aPixSize.Height() );
817         else
818             a2 += Point( 0, i );
819 
820         pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) );
821     }
822 
823     pOut->Pop();
824 
825 }
826 
827 sal_Bool EmbeddedObjectRef::TryRunningState()
828 {
829     return TryRunningState( mxObj );
830 }
831 
832 sal_Bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj )
833 {
834     if ( !xEmbObj.is() )
835         return sal_False;
836 
837     try
838     {
839         if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED )
840             xEmbObj->changeState( embed::EmbedStates::RUNNING );
841     }
842     catch ( uno::Exception& )
843     {
844         return sal_False;
845     }
846 
847     return sal_True;
848 }
849 
850 void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic,
851                                                 comphelper::EmbeddedObjectContainer& aContainer,
852                                                 const ::rtl::OUString& aName,
853                                                 const ::rtl::OUString& aMediaType )
854 {
855     SvMemoryStream aStream;
856     aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
857     if ( rGraphic.ExportNative( aStream ) )
858     {
859         aStream.Seek( 0 );
860 
861         uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream );
862         aContainer.InsertGraphicStream( xStream, aName, aMediaType );
863     }
864     else
865         OSL_ENSURE( sal_False, "Export of graphic is failed!\n" );
866 }
867 
868 sal_Bool EmbeddedObjectRef::ObjectIsModified( const uno::Reference< embed::XEmbeddedObject >& xObj )
869     throw( uno::Exception )
870 {
871     sal_Bool bResult = sal_False;
872 
873     sal_Int32 nState = xObj->getCurrentState();
874     if ( nState != embed::EmbedStates::LOADED && nState != embed::EmbedStates::RUNNING )
875     {
876         // the object is active so if the model is modified the replacement
877         // should be retrieved from the object
878         uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
879         if ( xModifiable.is() )
880             bResult = xModifiable->isModified();
881     }
882 
883     return bResult;
884 }
885 
886 uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream(
887                                                                 sal_Int64 nViewAspect,
888                                                                 const uno::Reference< embed::XEmbeddedObject >& xObj,
889                                                                 ::rtl::OUString* pMediaType )
890     throw()
891 {
892     return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType);
893 }
894 
895 void EmbeddedObjectRef::UpdateReplacementOnDemand()
896 {
897     DELETEZ( mpImp->pGraphic );
898     mpImp->bNeedUpdate = sal_True;
899     if ( mpImp->pHCGraphic )
900         DELETEZ( mpImp->pHCGraphic );
901     mpImp->mnGraphicVersion++;
902 
903     if( mpImp->pContainer )
904     {
905         //remove graphic from container thus a new up to date one is requested on save
906         mpImp->pContainer->RemoveGraphicStream( mpImp->aPersistName );
907     }
908 }
909 
910 sal_Bool EmbeddedObjectRef::IsChart() const
911 {
912     //todo maybe for 3.0:
913     //if the changes work good for chart
914     //we should apply them for all own ole objects
915 
916     //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary
917     //as this call can be very expensive and does block the user interface as long at it takes
918 
919     if ( !mxObj.is() )
920         return false;
921 
922     SvGlobalName aObjClsId( mxObj->getClassID() );
923     if(
924         SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId
925         || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId
926         || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId
927         || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId)
928     {
929         return sal_True;
930     }
931 
932     return sal_False;
933 }
934 
935 // #i104867#
936 sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const
937 {
938     return mpImp->mnGraphicVersion;
939 }
940 
941 void EmbeddedObjectRef::SetDefaultSizeForChart( const Size& rSizeIn_100TH_MM )
942 {
943     //#i103460# charts do not necessaryly have an own size within ODF files,
944     //for this case they need to use the size settings from the surrounding frame,
945     //which is made available with this method
946 
947     mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size( rSizeIn_100TH_MM.getWidth(), rSizeIn_100TH_MM.getHeight() );
948 
949     ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( mxObj, uno::UNO_QUERY );
950     DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
951     if( xSizeTransmitter.is() )
952         xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM );
953 }
954 
955 } // namespace svt
956 
957