xref: /aoo42x/main/svtools/source/misc/embedhlp.cxx (revision 4fa9ac85)
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