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