xref: /AOO41X/main/svtools/source/misc/embedhlp.cxx (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
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 }
307 /*
308 EmbeddedObjectRef& EmbeddedObjectRef::operator = ( const EmbeddedObjectRef& rObj )
309 {
310     DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" );
311 
312     delete mpImp->pGraphic;
313     if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic );
314     Clear();
315 
316     mpImp->nViewAspect = rObj.mpImp->nViewAspect;
317     mpImp->bIsLocked = rObj.mpImp->bIsLocked;
318     mxObj = rObj.mxObj;
319     mpImp->xListener = EmbedEventListener_Impl::Create( this );
320     mpImp->pContainer = rObj.mpImp->pContainer;
321     mpImp->aPersistName = rObj.mpImp->aPersistName;
322     mpImp->aMediaType = rObj.mpImp->aMediaType;
323     mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate;
324 
325     if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate )
326         mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic );
327     else
328         mpImp->pGraphic = 0;
329     return *this;
330 }
331 */
332 void EmbeddedObjectRef::Assign( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect )
333 {
334     DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" );
335 
336     Clear();
337     mpImp->nViewAspect = nAspect;
338     mxObj = xObj;
339     mpImp->xListener = EmbedEventListener_Impl::Create( this );
340 
341     //#i103460#
342     if ( IsChart() )
343     {
344         ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( xObj, uno::UNO_QUERY );
345         DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
346         if( xSizeTransmitter.is() )
347             xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM );
348     }
349 }
350 
351 void EmbeddedObjectRef::Clear()
352 {
353     if ( mxObj.is() && mpImp->xListener )
354     {
355         mxObj->removeStateChangeListener( mpImp->xListener );
356 
357         uno::Reference < util::XCloseable > xClose( mxObj, uno::UNO_QUERY );
358         if ( xClose.is() )
359             xClose->removeCloseListener( mpImp->xListener );
360 
361         uno::Reference < document::XEventBroadcaster > xBrd( mxObj, uno::UNO_QUERY );
362         if ( xBrd.is() )
363             xBrd->removeEventListener( mpImp->xListener );
364 
365         if ( mpImp->bIsLocked )
366         {
367             if ( xClose.is() )
368             {
369                 try
370                 {
371                     mxObj->changeState( embed::EmbedStates::LOADED );
372                     xClose->close( sal_True );
373                 }
374                 catch ( util::CloseVetoException& )
375                 {
376                     // there's still someone who needs the object!
377                 }
378                 catch ( uno::Exception& )
379                 {
380                     OSL_ENSURE( sal_False, "Error on switching of the object to loaded state and closing!\n" );
381                 }
382             }
383         }
384 
385         if ( mpImp->xListener )
386         {
387             mpImp->xListener->pObject = 0;
388             mpImp->xListener->release();
389             mpImp->xListener = 0;
390         }
391 
392         mxObj = 0;
393         mpImp->bNeedUpdate = sal_False;
394     }
395 
396     mpImp->pContainer = 0;
397     mpImp->bIsLocked = sal_False;
398     mpImp->bNeedUpdate = sal_False;
399 }
400 
401 void EmbeddedObjectRef::AssignToContainer( comphelper::EmbeddedObjectContainer* pContainer, const ::rtl::OUString& rPersistName )
402 {
403     mpImp->pContainer = pContainer;
404     mpImp->aPersistName = rPersistName;
405 
406     if ( mpImp->pGraphic && !mpImp->bNeedUpdate && pContainer )
407         SetGraphicToContainer( *mpImp->pGraphic, *pContainer, mpImp->aPersistName, ::rtl::OUString() );
408 }
409 
410 comphelper::EmbeddedObjectContainer* EmbeddedObjectRef::GetContainer() const
411 {
412     return mpImp->pContainer;
413 }
414 
415 ::rtl::OUString EmbeddedObjectRef::GetPersistName() const
416 {
417     return mpImp->aPersistName;
418 }
419 
420 MapUnit EmbeddedObjectRef::GetMapUnit() const
421 {
422     if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT )
423         return VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) );
424     else
425         // TODO/LATER: currently only CONTENT aspect requires communication with the object
426         return MAP_100TH_MM;
427 }
428 
429 sal_Int64 EmbeddedObjectRef::GetViewAspect() const
430 {
431     return mpImp->nViewAspect;
432 }
433 
434 void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect )
435 {
436     mpImp->nViewAspect = nAspect;
437 }
438 
439 void EmbeddedObjectRef::Lock( sal_Bool bLock )
440 {
441     mpImp->bIsLocked = bLock;
442 }
443 
444 sal_Bool EmbeddedObjectRef::IsLocked() const
445 {
446     return mpImp->bIsLocked;
447 }
448 
449 void EmbeddedObjectRef::GetReplacement( sal_Bool bUpdate )
450 {
451     if ( bUpdate )
452     {
453         DELETEZ( mpImp->pGraphic );
454         mpImp->aMediaType = ::rtl::OUString();
455         mpImp->pGraphic = new Graphic;
456         if ( mpImp->pHCGraphic )
457             DELETEZ( mpImp->pHCGraphic );
458         mpImp->mnGraphicVersion++;
459     }
460     else if ( !mpImp->pGraphic )
461     {
462         mpImp->pGraphic = new Graphic;
463         mpImp->mnGraphicVersion++;
464     }
465     else
466     {
467         DBG_ERROR("No update, but replacement exists already!");
468         return;
469     }
470 
471     SvStream* pGraphicStream = GetGraphicStream( bUpdate );
472     if ( pGraphicStream )
473     {
474         GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
475         if( mpImp->pGraphic )
476             pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
477         mpImp->mnGraphicVersion++;
478         delete pGraphicStream;
479     }
480 }
481 
482 Graphic* EmbeddedObjectRef::GetGraphic( ::rtl::OUString* pMediaType ) const
483 {
484     if ( mpImp->bNeedUpdate )
485         // bNeedUpdate will be set to false while retrieving new replacement
486         const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_True );
487     else if ( !mpImp->pGraphic )
488         const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_False );
489 
490     if ( mpImp->pGraphic && pMediaType )
491         *pMediaType = mpImp->aMediaType;
492     return mpImp->pGraphic;
493 }
494 
495 Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const
496 {
497     MapMode aSourceMapMode( MAP_100TH_MM );
498     Size aResult;
499 
500     if ( mpImp->nViewAspect == embed::Aspects::MSOLE_ICON )
501     {
502         Graphic* pGraphic = GetGraphic();
503         if ( pGraphic )
504         {
505             aSourceMapMode = pGraphic->GetPrefMapMode();
506             aResult = pGraphic->GetPrefSize();
507         }
508         else
509             aResult = Size( 2500, 2500 );
510     }
511     else
512     {
513         awt::Size aSize;
514 
515         if ( mxObj.is() )
516         {
517             try
518             {
519                 aSize = mxObj->getVisualAreaSize( mpImp->nViewAspect );
520             }
521             catch( embed::NoVisualAreaSizeException& )
522             {
523             }
524             catch( uno::Exception& )
525             {
526                 OSL_ENSURE( sal_False, "Something went wrong on getting of the size of the object!" );
527             }
528 
529             try
530             {
531                 aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) );
532             }
533             catch( uno::Exception )
534             {
535                 OSL_ENSURE( sal_False, "Can not get the map mode!" );
536             }
537         }
538 
539         if ( !aSize.Height && !aSize.Width )
540         {
541             aSize.Width = 5000;
542             aSize.Height = 5000;
543         }
544 
545         aResult = Size( aSize.Width, aSize.Height );
546     }
547 
548     if ( pTargetMapMode )
549         aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode );
550 
551     return aResult;
552 }
553 
554 Graphic* EmbeddedObjectRef::GetHCGraphic() const
555 {
556     if ( !mpImp->pHCGraphic )
557     {
558         uno::Reference< io::XInputStream > xInStream;
559         try
560         {
561             // if the object needs size on load, that means that it is not our object
562             // currently the HC mode is supported only for OOo own objects so the following
563             // check is used as an optimization
564             // TODO/LATER: shouldn't there be a special status flag to detect alien implementation?
565             if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT
566               && mxObj.is() && !( mxObj->getStatus( mpImp->nViewAspect ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD ) )
567             {
568                 // TODO/LATER: optimization, it makes no sence to do it for OLE objects
569                 if ( mxObj->getCurrentState() == embed::EmbedStates::LOADED )
570                     mxObj->changeState( embed::EmbedStates::RUNNING );
571 
572                 // TODO: return for the aspect of the document
573                 embed::VisualRepresentation aVisualRepresentation;
574                 uno::Reference< datatransfer::XTransferable > xTransferable( mxObj->getComponent(), uno::UNO_QUERY );
575                 if ( !xTransferable.is() )
576                     throw uno::RuntimeException();
577 
578                 datatransfer::DataFlavor aDataFlavor(
579                         ::rtl::OUString::createFromAscii(
580                                 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" ),
581                         ::rtl::OUString::createFromAscii( "GDIMetaFile" ),
582                         ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
583 
584                 uno::Sequence < sal_Int8 > aSeq;
585                 if ( ( xTransferable->getTransferData( aDataFlavor ) >>= aSeq ) && aSeq.getLength() )
586                     xInStream = new ::comphelper::SequenceInputStream( aSeq );
587             }
588         }
589         catch ( uno::Exception& )
590         {
591         }
592 
593         if ( xInStream.is() )
594         {
595             SvStream* pStream = NULL;
596             pStream = ::utl::UcbStreamHelper::CreateStream( xInStream );
597             if ( pStream )
598             {
599                 if ( !pStream->GetError() )
600                 {
601                     GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
602                     Graphic* pGraphic = new Graphic();
603                     if ( pGF->ImportGraphic( *pGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW ) == 0 )
604                         mpImp->pHCGraphic = pGraphic;
605                     else
606                         delete pGraphic;
607                     mpImp->mnGraphicVersion++;
608                 }
609 
610                 delete pStream;
611             }
612         }
613     }
614 
615     return mpImp->pHCGraphic;
616 }
617 
618 void EmbeddedObjectRef::SetGraphicStream( const uno::Reference< io::XInputStream >& xInGrStream,
619                                             const ::rtl::OUString& rMediaType )
620 {
621     if ( mpImp->pGraphic )
622         delete mpImp->pGraphic;
623     mpImp->pGraphic = new Graphic();
624     mpImp->aMediaType = rMediaType;
625     if ( mpImp->pHCGraphic )
626         DELETEZ( mpImp->pHCGraphic );
627     mpImp->mnGraphicVersion++;
628 
629     SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( xInGrStream );
630 
631     if ( pGraphicStream )
632     {
633         GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
634         pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
635         mpImp->mnGraphicVersion++;
636 
637         if ( mpImp->pContainer )
638         {
639             pGraphicStream->Seek( 0 );
640             uno::Reference< io::XInputStream > xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream );
641 
642             mpImp->pContainer->InsertGraphicStream( xInSeekGrStream, mpImp->aPersistName, rMediaType );
643         }
644 
645         delete pGraphicStream;
646     }
647 
648     mpImp->bNeedUpdate = sal_False;
649 
650 }
651 
652 void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const ::rtl::OUString& rMediaType )
653 {
654     if ( mpImp->pGraphic )
655         delete mpImp->pGraphic;
656     mpImp->pGraphic = new Graphic( rGraphic );
657     mpImp->aMediaType = rMediaType;
658     if ( mpImp->pHCGraphic )
659         DELETEZ( mpImp->pHCGraphic );
660     mpImp->mnGraphicVersion++;
661 
662     if ( mpImp->pContainer )
663         SetGraphicToContainer( rGraphic, *mpImp->pContainer, mpImp->aPersistName, rMediaType );
664 
665     mpImp->bNeedUpdate = sal_False;
666 }
667 
668 SvStream* EmbeddedObjectRef::GetGraphicStream( sal_Bool bUpdate ) const
669 {
670     RTL_LOGFILE_CONTEXT( aLog, "svtools (mv76033) svt::EmbeddedObjectRef::GetGraphicStream" );
671     DBG_ASSERT( bUpdate || mpImp->pContainer, "Can't retrieve current graphic!" );
672     uno::Reference < io::XInputStream > xStream;
673     if ( mpImp->pContainer && !bUpdate )
674     {
675         RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from container" );
676         // try to get graphic stream from container storage
677         xStream = mpImp->pContainer->GetGraphicStream( mxObj, &mpImp->aMediaType );
678         if ( xStream.is() )
679         {
680             const sal_Int32 nConstBufferSize = 32000;
681             SvStream *pStream = new SvMemoryStream( 32000, 32000 );
682             sal_Int32 nRead=0;
683             uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
684             do
685             {
686                 nRead = xStream->readBytes ( aSequence, nConstBufferSize );
687                 pStream->Write( aSequence.getConstArray(), nRead );
688             }
689             while ( nRead == nConstBufferSize );
690             pStream->Seek(0);
691             return pStream;
692         }
693     }
694 
695     if ( !xStream.is() )
696     {
697         RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from object" );
698         // update wanted or no stream in container storage available
699         xStream = GetGraphicReplacementStream( mpImp->nViewAspect, mxObj, &mpImp->aMediaType );
700 
701         if ( xStream.is() )
702         {
703             if ( mpImp->pContainer )
704                 mpImp->pContainer->InsertGraphicStream( xStream, mpImp->aPersistName, mpImp->aMediaType );
705 
706             SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream );
707             if ( pResult && bUpdate )
708                 mpImp->bNeedUpdate = sal_False;
709 
710             return pResult;
711         }
712     }
713 
714     return NULL;
715 }
716 
717 void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const String &rText, OutputDevice *pOut )
718 {
719     MapMode aMM( MAP_APPFONT );
720     Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL );
721     Font aFnt( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Helvetica" ) ), aAppFontSz );
722     aFnt.SetTransparent( sal_True );
723     aFnt.SetColor( Color( COL_LIGHTRED ) );
724     aFnt.SetWeight( WEIGHT_BOLD );
725     aFnt.SetFamily( FAMILY_SWISS );
726 
727     pOut->Push();
728     pOut->SetBackground();
729     pOut->SetFont( aFnt );
730 
731     Point aPt;
732     // Nun den Text so skalieren, dass er in das Rect passt.
733     // Wir fangen mit der Defaultsize an und gehen 1-AppFont runter
734     for( sal_uInt16 i = 8; i > 2; i-- )
735     {
736         aPt.X() = (rRect.GetWidth()  - pOut->GetTextWidth( rText )) / 2;
737         aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2;
738 
739         sal_Bool bTiny = sal_False;
740         if( aPt.X() < 0 ) bTiny = sal_True, aPt.X() = 0;
741         if( aPt.Y() < 0 ) bTiny = sal_True, aPt.Y() = 0;
742         if( bTiny )
743         {
744             // heruntergehen bei kleinen Bildern
745             aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) );
746             pOut->SetFont( aFnt );
747         }
748         else
749             break;
750     }
751 
752     Bitmap aBmp( SvtResId( BMP_PLUGIN ) );
753     long nHeight = rRect.GetHeight() - pOut->GetTextHeight();
754     long nWidth = rRect.GetWidth();
755     if( nHeight > 0 )
756     {
757         aPt.Y() = nHeight;
758         Point   aP = rRect.TopLeft();
759         Size    aBmpSize = aBmp.GetSizePixel();
760         // Bitmap einpassen
761         if( nHeight * 10 / nWidth
762           > aBmpSize.Height() * 10 / aBmpSize.Width() )
763         {
764             // nach der Breite ausrichten
765             // Proportion beibehalten
766             long nH = nWidth * aBmpSize.Height() / aBmpSize.Width();
767             // zentrieren
768             aP.Y() += (nHeight - nH) / 2;
769             nHeight = nH;
770         }
771         else
772         {
773             // nach der H"ohe ausrichten
774             // Proportion beibehalten
775             long nW = nHeight * aBmpSize.Width() / aBmpSize.Height();
776             // zentrieren
777             aP.X() += (nWidth - nW) / 2;
778             nWidth = nW;
779         }
780 
781         pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp );
782     }
783 
784     pOut->IntersectClipRegion( rRect );
785     aPt += rRect.TopLeft();
786     pOut->DrawText( aPt, rText );
787     pOut->Pop();
788 }
789 
790 void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut )
791 {
792     GDIMetaFile * pMtf = pOut->GetConnectMetaFile();
793     if( pMtf && pMtf->IsRecord() )
794         return;
795 
796     pOut->Push();
797     pOut->SetLineColor( Color( COL_BLACK ) );
798 
799     Size aPixSize = pOut->LogicToPixel( rRect.GetSize() );
800     aPixSize.Width() -= 1;
801     aPixSize.Height() -= 1;
802     Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() );
803     sal_Int32 nMax = aPixSize.Width() + aPixSize.Height();
804     for( sal_Int32 i = 5; i < nMax; i += 5 )
805     {
806         Point a1( aPixViewPos ), a2( aPixViewPos );
807         if( i > aPixSize.Width() )
808             a1 += Point( aPixSize.Width(), i - aPixSize.Width() );
809         else
810             a1 += Point( i, 0 );
811         if( i > aPixSize.Height() )
812             a2 += Point( i - aPixSize.Height(), aPixSize.Height() );
813         else
814             a2 += Point( 0, i );
815 
816         pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) );
817     }
818 
819     pOut->Pop();
820 
821 }
822 
823 sal_Bool EmbeddedObjectRef::TryRunningState()
824 {
825     return TryRunningState( mxObj );
826 }
827 
828 sal_Bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj )
829 {
830     if ( !xEmbObj.is() )
831         return sal_False;
832 
833     try
834     {
835         if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED )
836             xEmbObj->changeState( embed::EmbedStates::RUNNING );
837     }
838     catch ( uno::Exception& )
839     {
840         return sal_False;
841     }
842 
843     return sal_True;
844 }
845 
846 void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic,
847                                                 comphelper::EmbeddedObjectContainer& aContainer,
848                                                 const ::rtl::OUString& aName,
849                                                 const ::rtl::OUString& aMediaType )
850 {
851     SvMemoryStream aStream;
852     aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
853     if ( rGraphic.ExportNative( aStream ) )
854     {
855         aStream.Seek( 0 );
856 
857         uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream );
858         aContainer.InsertGraphicStream( xStream, aName, aMediaType );
859     }
860     else
861         OSL_ENSURE( sal_False, "Export of graphic is failed!\n" );
862 }
863 
864 sal_Bool EmbeddedObjectRef::ObjectIsModified( const uno::Reference< embed::XEmbeddedObject >& xObj )
865     throw( uno::Exception )
866 {
867     sal_Bool bResult = sal_False;
868 
869     sal_Int32 nState = xObj->getCurrentState();
870     if ( nState != embed::EmbedStates::LOADED && nState != embed::EmbedStates::RUNNING )
871     {
872         // the object is active so if the model is modified the replacement
873         // should be retrieved from the object
874         uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
875         if ( xModifiable.is() )
876             bResult = xModifiable->isModified();
877     }
878 
879     return bResult;
880 }
881 
882 uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream(
883                                                                 sal_Int64 nViewAspect,
884                                                                 const uno::Reference< embed::XEmbeddedObject >& xObj,
885                                                                 ::rtl::OUString* pMediaType )
886     throw()
887 {
888     return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType);
889 }
890 
891 void EmbeddedObjectRef::UpdateReplacementOnDemand()
892 {
893     DELETEZ( mpImp->pGraphic );
894     mpImp->bNeedUpdate = sal_True;
895     if ( mpImp->pHCGraphic )
896         DELETEZ( mpImp->pHCGraphic );
897     mpImp->mnGraphicVersion++;
898 
899     if( mpImp->pContainer )
900     {
901         //remove graphic from container thus a new up to date one is requested on save
902         mpImp->pContainer->RemoveGraphicStream( mpImp->aPersistName );
903     }
904 }
905 
906 sal_Bool EmbeddedObjectRef::IsChart() const
907 {
908     //todo maybe for 3.0:
909     //if the changes work good for chart
910     //we should apply them for all own ole objects
911 
912     //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary
913     //as this call can be very expensive and does block the user interface as long at it takes
914 
915     if ( !mxObj.is() )
916         return false;
917 
918     SvGlobalName aObjClsId( mxObj->getClassID() );
919     if(
920         SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId
921         || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId
922         || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId
923         || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId)
924     {
925         return sal_True;
926     }
927 
928     return sal_False;
929 }
930 
931 // #i104867#
932 sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const
933 {
934     return mpImp->mnGraphicVersion;
935 }
936 
937 void EmbeddedObjectRef::SetDefaultSizeForChart( const Size& rSizeIn_100TH_MM )
938 {
939     //#i103460# charts do not necessaryly have an own size within ODF files,
940     //for this case they need to use the size settings from the surrounding frame,
941     //which is made available with this method
942 
943     mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size( rSizeIn_100TH_MM.getWidth(), rSizeIn_100TH_MM.getHeight() );
944 
945     ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( mxObj, uno::UNO_QUERY );
946     DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
947     if( xSizeTransmitter.is() )
948         xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM );
949 }
950 
951 } // namespace svt
952 
953