xref: /trunk/main/svtools/source/misc/embedhlp.cxx (revision 2c35faf5)
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     try
486     {
487         if ( mpImp->bNeedUpdate )
488             // bNeedUpdate will be set to false while retrieving new replacement
489             const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_True );
490         else if ( !mpImp->pGraphic )
491             const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_False );
492     }
493 	catch( uno::Exception& )
494 	{
495 		OSL_ENSURE( sal_False, "Something went wrong on getting the graphic!" );
496 	}
497 
498     if ( mpImp->pGraphic && pMediaType )
499         *pMediaType = mpImp->aMediaType;
500     return mpImp->pGraphic;
501 }
502 
503 Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const
504 {
505 	MapMode aSourceMapMode( MAP_100TH_MM );
506 	Size aResult;
507 
508 	if ( mpImp->nViewAspect == embed::Aspects::MSOLE_ICON )
509 	{
510 		Graphic* pGraphic = GetGraphic();
511 		if ( pGraphic )
512 		{
513 			aSourceMapMode = pGraphic->GetPrefMapMode();
514 			aResult = pGraphic->GetPrefSize();
515 		}
516 		else
517 			aResult = Size( 2500, 2500 );
518 	}
519 	else
520 	{
521 		awt::Size aSize;
522 
523 		if ( mxObj.is() )
524 		{
525 			try
526 			{
527 				aSize = mxObj->getVisualAreaSize( mpImp->nViewAspect );
528 			}
529 			catch( embed::NoVisualAreaSizeException& )
530 			{
531 			}
532 			catch( uno::Exception& )
533 			{
534 				OSL_ENSURE( sal_False, "Something went wrong on getting of the size of the object!" );
535 			}
536 
537 			try
538 			{
539 				aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) );
540 			}
541 			catch( uno::Exception )
542 			{
543 				OSL_ENSURE( sal_False, "Can not get the map mode!" );
544 			}
545 		}
546 
547 		if ( !aSize.Height && !aSize.Width )
548 		{
549 			aSize.Width = 5000;
550 			aSize.Height = 5000;
551 		}
552 
553 		aResult = Size( aSize.Width, aSize.Height );
554 	}
555 
556 	if ( pTargetMapMode )
557 		aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode );
558 
559 	return aResult;
560 }
561 
562 Graphic* EmbeddedObjectRef::GetHCGraphic() const
563 {
564 	if ( !mpImp->pHCGraphic )
565 	{
566 		uno::Reference< io::XInputStream > xInStream;
567 		try
568 		{
569 			// if the object needs size on load, that means that it is not our object
570 			// currently the HC mode is supported only for OOo own objects so the following
571 			// check is used as an optimization
572 			// TODO/LATER: shouldn't there be a special status flag to detect alien implementation?
573 			if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT
574 			  && mxObj.is() && !( mxObj->getStatus( mpImp->nViewAspect ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD ) )
575 			{
576 				// TODO/LATER: optimization, it makes no sence to do it for OLE objects
577 				if ( mxObj->getCurrentState() == embed::EmbedStates::LOADED )
578 					mxObj->changeState( embed::EmbedStates::RUNNING );
579 
580 				// TODO: return for the aspect of the document
581 				embed::VisualRepresentation aVisualRepresentation;
582     			uno::Reference< datatransfer::XTransferable > xTransferable( mxObj->getComponent(), uno::UNO_QUERY );
583 				if ( !xTransferable.is() )
584 					throw uno::RuntimeException();
585 
586 				datatransfer::DataFlavor aDataFlavor(
587             			::rtl::OUString::createFromAscii(
588 								"application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" ),
589 						::rtl::OUString::createFromAscii( "GDIMetaFile" ),
590 						::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
591 
592 				uno::Sequence < sal_Int8 > aSeq;
593 				if ( ( xTransferable->getTransferData( aDataFlavor ) >>= aSeq ) && aSeq.getLength() )
594 					xInStream = new ::comphelper::SequenceInputStream( aSeq );
595 			}
596 		}
597 		catch ( uno::Exception& )
598 		{
599     		OSL_ENSURE( sal_False, "Something went wrong on getting the high contrast graphic!" );
600 		}
601 
602 		if ( xInStream.is() )
603 		{
604 			SvStream* pStream = NULL;
605 			pStream = ::utl::UcbStreamHelper::CreateStream( xInStream );
606 			if ( pStream )
607 			{
608 				if ( !pStream->GetError() )
609 				{
610         			GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
611 					Graphic* pGraphic = new Graphic();
612         			if ( pGF->ImportGraphic( *pGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW ) == 0 )
613 						mpImp->pHCGraphic = pGraphic;
614 					else
615 						delete pGraphic;
616                     mpImp->mnGraphicVersion++;
617 				}
618 
619         		delete pStream;
620 			}
621 		}
622 	}
623 
624 	return mpImp->pHCGraphic;
625 }
626 
627 void EmbeddedObjectRef::SetGraphicStream( const uno::Reference< io::XInputStream >& xInGrStream,
628 											const ::rtl::OUString& rMediaType )
629 {
630     if ( mpImp->pGraphic )
631         delete mpImp->pGraphic;
632     mpImp->pGraphic = new Graphic();
633     mpImp->aMediaType = rMediaType;
634 	if ( mpImp->pHCGraphic )
635         DELETEZ( mpImp->pHCGraphic );
636     mpImp->mnGraphicVersion++;
637 
638     SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( xInGrStream );
639 
640     if ( pGraphicStream )
641     {
642         GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
643         pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
644         mpImp->mnGraphicVersion++;
645 
646 		if ( mpImp->pContainer )
647 		{
648 			pGraphicStream->Seek( 0 );
649 			uno::Reference< io::XInputStream > xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream );
650 
651     		mpImp->pContainer->InsertGraphicStream( xInSeekGrStream, mpImp->aPersistName, rMediaType );
652 		}
653 
654         delete pGraphicStream;
655 	}
656 
657     mpImp->bNeedUpdate = sal_False;
658 
659 }
660 
661 void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const ::rtl::OUString& rMediaType )
662 {
663     if ( mpImp->pGraphic )
664         delete mpImp->pGraphic;
665     mpImp->pGraphic = new Graphic( rGraphic );
666     mpImp->aMediaType = rMediaType;
667 	if ( mpImp->pHCGraphic )
668         DELETEZ( mpImp->pHCGraphic );
669     mpImp->mnGraphicVersion++;
670 
671     if ( mpImp->pContainer )
672 		SetGraphicToContainer( rGraphic, *mpImp->pContainer, mpImp->aPersistName, rMediaType );
673 
674     mpImp->bNeedUpdate = sal_False;
675 }
676 
677 SvStream* EmbeddedObjectRef::GetGraphicStream( sal_Bool bUpdate ) const
678 {
679 	RTL_LOGFILE_CONTEXT( aLog, "svtools (mv76033) svt::EmbeddedObjectRef::GetGraphicStream" );
680     DBG_ASSERT( bUpdate || mpImp->pContainer, "Can't retrieve current graphic!" );
681     uno::Reference < io::XInputStream > xStream;
682     if ( mpImp->pContainer && !bUpdate )
683     {
684 		RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from container" );
685         // try to get graphic stream from container storage
686         xStream = mpImp->pContainer->GetGraphicStream( mxObj, &mpImp->aMediaType );
687         if ( xStream.is() )
688         {
689             const sal_Int32 nConstBufferSize = 32000;
690             SvStream *pStream = new SvMemoryStream( 32000, 32000 );
691             sal_Int32 nRead=0;
692             uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
693             do
694             {
695                 nRead = xStream->readBytes ( aSequence, nConstBufferSize );
696                 pStream->Write( aSequence.getConstArray(), nRead );
697             }
698             while ( nRead == nConstBufferSize );
699             pStream->Seek(0);
700             return pStream;
701         }
702     }
703 
704     if ( !xStream.is() )
705     {
706 		RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from object" );
707         // update wanted or no stream in container storage available
708 		xStream = GetGraphicReplacementStream( mpImp->nViewAspect, mxObj, &mpImp->aMediaType );
709 
710 		if ( xStream.is() )
711 		{
712 			if ( mpImp->pContainer )
713             	mpImp->pContainer->InsertGraphicStream( xStream, mpImp->aPersistName, mpImp->aMediaType );
714 
715             SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream );
716             if ( pResult && bUpdate )
717                 mpImp->bNeedUpdate = sal_False;
718 
719             return pResult;
720         }
721     }
722 
723     return NULL;
724 }
725 
726 void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const String &rText, OutputDevice *pOut )
727 {
728 	MapMode aMM( MAP_APPFONT );
729 	Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL );
730 	Font aFnt( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Helvetica" ) ), aAppFontSz );
731 	aFnt.SetTransparent( sal_True );
732 	aFnt.SetColor( Color( COL_LIGHTRED ) );
733 	aFnt.SetWeight( WEIGHT_BOLD );
734 	aFnt.SetFamily( FAMILY_SWISS );
735 
736 	pOut->Push();
737 	pOut->SetBackground();
738 	pOut->SetFont( aFnt );
739 
740 	Point aPt;
741 	// Nun den Text so skalieren, dass er in das Rect passt.
742 	// Wir fangen mit der Defaultsize an und gehen 1-AppFont runter
743 	for( sal_uInt16 i = 8; i > 2; i-- )
744 	{
745 		aPt.X() = (rRect.GetWidth()  - pOut->GetTextWidth( rText )) / 2;
746 		aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2;
747 
748 		sal_Bool bTiny = sal_False;
749 		if( aPt.X() < 0 ) bTiny = sal_True, aPt.X() = 0;
750 		if( aPt.Y() < 0 ) bTiny = sal_True, aPt.Y() = 0;
751 		if( bTiny )
752 		{
753 			// heruntergehen bei kleinen Bildern
754 			aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) );
755 			pOut->SetFont( aFnt );
756 		}
757 		else
758 			break;
759 	}
760 
761     Bitmap aBmp( SvtResId( BMP_PLUGIN ) );
762 	long nHeight = rRect.GetHeight() - pOut->GetTextHeight();
763 	long nWidth = rRect.GetWidth();
764 	if( nHeight > 0 )
765 	{
766 		aPt.Y() = nHeight;
767 		Point	aP = rRect.TopLeft();
768 		Size	aBmpSize = aBmp.GetSizePixel();
769 		// Bitmap einpassen
770 		if( nHeight * 10 / nWidth
771 		  > aBmpSize.Height() * 10 / aBmpSize.Width() )
772 		{
773 			// nach der Breite ausrichten
774 			// Proportion beibehalten
775 			long nH = nWidth * aBmpSize.Height() / aBmpSize.Width();
776 			// zentrieren
777 			aP.Y() += (nHeight - nH) / 2;
778 			nHeight = nH;
779 		}
780 		else
781 		{
782 			// nach der H"ohe ausrichten
783 			// Proportion beibehalten
784 			long nW = nHeight * aBmpSize.Width() / aBmpSize.Height();
785 			// zentrieren
786 			aP.X() += (nWidth - nW) / 2;
787 			nWidth = nW;
788 		}
789 
790 		pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp );
791 	}
792 
793 	pOut->IntersectClipRegion( rRect );
794 	aPt += rRect.TopLeft();
795 	pOut->DrawText( aPt, rText );
796 	pOut->Pop();
797 }
798 
799 void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut )
800 {
801 	GDIMetaFile * pMtf = pOut->GetConnectMetaFile();
802 	if( pMtf && pMtf->IsRecord() )
803 		return;
804 
805 	pOut->Push();
806 	pOut->SetLineColor( Color( COL_BLACK ) );
807 
808 	Size aPixSize = pOut->LogicToPixel( rRect.GetSize() );
809 	aPixSize.Width() -= 1;
810 	aPixSize.Height() -= 1;
811 	Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() );
812 	sal_Int32 nMax = aPixSize.Width() + aPixSize.Height();
813 	for( sal_Int32 i = 5; i < nMax; i += 5 )
814 	{
815 		Point a1( aPixViewPos ), a2( aPixViewPos );
816 		if( i > aPixSize.Width() )
817 			a1 += Point( aPixSize.Width(), i - aPixSize.Width() );
818 		else
819 			a1 += Point( i, 0 );
820 		if( i > aPixSize.Height() )
821 			a2 += Point( i - aPixSize.Height(), aPixSize.Height() );
822 		else
823 			a2 += Point( 0, i );
824 
825 		pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) );
826 	}
827 
828 	pOut->Pop();
829 
830 }
831 
832 sal_Bool EmbeddedObjectRef::TryRunningState()
833 {
834     return TryRunningState( mxObj );
835 }
836 
837 sal_Bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj )
838 {
839 	if ( !xEmbObj.is() )
840 		return sal_False;
841 
842     try
843     {
844         if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED )
845             xEmbObj->changeState( embed::EmbedStates::RUNNING );
846     }
847     catch ( uno::Exception& )
848     {
849         return sal_False;
850     }
851 
852     return sal_True;
853 }
854 
855 void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic,
856                                                 comphelper::EmbeddedObjectContainer& aContainer,
857                                                 const ::rtl::OUString& aName,
858 												const ::rtl::OUString& aMediaType )
859 {
860     SvMemoryStream aStream;
861     aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
862     if ( rGraphic.ExportNative( aStream ) )
863 	{
864 		aStream.Seek( 0 );
865 
866        	uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream );
867        	aContainer.InsertGraphicStream( xStream, aName, aMediaType );
868 	}
869     else
870         OSL_ENSURE( sal_False, "Export of graphic is failed!\n" );
871 }
872 
873 sal_Bool EmbeddedObjectRef::ObjectIsModified( const uno::Reference< embed::XEmbeddedObject >& xObj )
874 	throw( uno::Exception )
875 {
876 	sal_Bool bResult = sal_False;
877 
878 	sal_Int32 nState = xObj->getCurrentState();
879 	if ( nState != embed::EmbedStates::LOADED && nState != embed::EmbedStates::RUNNING )
880 	{
881 		// the object is active so if the model is modified the replacement
882 		// should be retrieved from the object
883 		uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
884 		if ( xModifiable.is() )
885 			bResult = xModifiable->isModified();
886 	}
887 
888 	return bResult;
889 }
890 
891 uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream(
892 																sal_Int64 nViewAspect,
893 																const uno::Reference< embed::XEmbeddedObject >& xObj,
894 																::rtl::OUString* pMediaType )
895 	throw()
896 {
897     return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType);
898 }
899 
900 void EmbeddedObjectRef::UpdateReplacementOnDemand()
901 {
902     DELETEZ( mpImp->pGraphic );
903     mpImp->bNeedUpdate = sal_True;
904 	if ( mpImp->pHCGraphic )
905         DELETEZ( mpImp->pHCGraphic );
906     mpImp->mnGraphicVersion++;
907 
908     if( mpImp->pContainer )
909     {
910         //remove graphic from container thus a new up to date one is requested on save
911         mpImp->pContainer->RemoveGraphicStream( mpImp->aPersistName );
912     }
913 }
914 
915 sal_Bool EmbeddedObjectRef::IsChart() const
916 {
917     //todo maybe for 3.0:
918     //if the changes work good for chart
919     //we should apply them for all own ole objects
920 
921     //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary
922     //as this call can be very expensive and does block the user interface as long at it takes
923 
924     if ( !mxObj.is() )
925         return false;
926 
927     SvGlobalName aObjClsId( mxObj->getClassID() );
928     if(
929         SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId
930         || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId
931         || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId
932         || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId)
933     {
934         return sal_True;
935     }
936 
937     return sal_False;
938 }
939 
940 // #i104867#
941 sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const
942 {
943     return mpImp->mnGraphicVersion;
944 }
945 
946 void EmbeddedObjectRef::SetDefaultSizeForChart( const Size& rSizeIn_100TH_MM )
947 {
948     //#i103460# charts do not necessaryly have an own size within ODF files,
949     //for this case they need to use the size settings from the surrounding frame,
950     //which is made available with this method
951 
952     mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size( rSizeIn_100TH_MM.getWidth(), rSizeIn_100TH_MM.getHeight() );
953 
954     ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( mxObj, uno::UNO_QUERY );
955     DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
956     if( xSizeTransmitter.is() )
957         xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM );
958 }
959 
960 } // namespace svt
961 
962