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