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