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 1196 : 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 900 : EmbedEventListener_Impl( EmbeddedObjectRef* p ) :
62 : pObject(p)
63 900 : , nState(-1)
64 900 : {}
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 900 : EmbedEventListener_Impl* EmbedEventListener_Impl::Create( EmbeddedObjectRef* p )
81 : {
82 900 : EmbedEventListener_Impl* xRet = new EmbedEventListener_Impl( p );
83 900 : xRet->acquire();
84 :
85 900 : if ( p->GetObject().is() )
86 : {
87 900 : p->GetObject()->addStateChangeListener( xRet );
88 :
89 900 : uno::Reference < util::XCloseable > xClose( p->GetObject(), uno::UNO_QUERY );
90 : DBG_ASSERT( xClose.is(), "Object does not support XCloseable!" );
91 900 : if ( xClose.is() )
92 900 : xClose->addCloseListener( xRet );
93 :
94 900 : uno::Reference < document::XEventBroadcaster > xBrd( p->GetObject(), uno::UNO_QUERY );
95 900 : if ( xBrd.is() )
96 900 : xBrd->addEventListener( xRet );
97 :
98 900 : xRet->nState = p->GetObject()->getCurrentState();
99 900 : if ( xRet->nState == embed::EmbedStates::RUNNING )
100 : {
101 874 : uno::Reference < util::XModifiable > xMod( p->GetObject()->getComponent(), uno::UNO_QUERY );
102 874 : if ( xMod.is() )
103 : // listen for changes in running state (update replacements in case of changes)
104 874 : xMod->addModifyListener( xRet );
105 900 : }
106 : }
107 :
108 900 : return xRet;
109 : }
110 :
111 126 : void SAL_CALL EmbedEventListener_Impl::changingState( const lang::EventObject&,
112 : ::sal_Int32,
113 : ::sal_Int32 )
114 : throw ( embed::WrongStateException,
115 : uno::RuntimeException )
116 : {
117 126 : }
118 :
119 120 : void SAL_CALL EmbedEventListener_Impl::stateChanged( const lang::EventObject&,
120 : ::sal_Int32 nOldState,
121 : ::sal_Int32 nNewState )
122 : throw ( uno::RuntimeException )
123 : {
124 120 : SolarMutexGuard aGuard;
125 120 : nState = nNewState;
126 120 : if ( !pObject )
127 120 : return;
128 :
129 120 : uno::Reference < util::XModifiable > xMod( pObject->GetObject()->getComponent(), uno::UNO_QUERY );
130 120 : 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 120 : else if ( nNewState == embed::EmbedStates::LOADED )
151 : {
152 : // in loaded state we can't listen
153 120 : if ( xMod.is() )
154 0 : xMod->removeModifyListener( this );
155 120 : }
156 : }
157 :
158 4704 : void SAL_CALL EmbedEventListener_Impl::modified( const lang::EventObject& ) throw (uno::RuntimeException)
159 : {
160 4704 : SolarMutexGuard aGuard;
161 4704 : if ( pObject && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON )
162 : {
163 4624 : if ( nState == embed::EmbedStates::RUNNING )
164 : {
165 : // updates only necessary in non-active states
166 4624 : if( pObject->IsChart() )
167 80 : pObject->UpdateReplacementOnDemand();
168 : else
169 4544 : 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 4704 : }
179 4704 : }
180 :
181 7912 : void SAL_CALL EmbedEventListener_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException )
182 : {
183 7912 : SolarMutexGuard aGuard;
184 :
185 7912 : if ( pObject && aEvent.EventName == "OnVisAreaChanged" && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON && !pObject->IsChart() )
186 : {
187 0 : pObject->UpdateReplacement();
188 7912 : }
189 7912 : }
190 :
191 96 : 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 96 : if ( pObject && pObject->IsLocked() && Source.Source == pObject->GetObject() )
198 96 : 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 694 : void SAL_CALL EmbedEventListener_Impl::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException )
211 : {
212 694 : if ( pObject && aEvent.Source == pObject->GetObject() )
213 : {
214 0 : pObject->Clear();
215 0 : pObject = 0;
216 : }
217 694 : }
218 :
219 1602 : 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 530 : void EmbeddedObjectRef::Construct_Impl()
236 : {
237 530 : mpImp = new EmbeddedObjectRef_Impl;
238 530 : mpImp->pContainer = 0;
239 530 : mpImp->pGraphic = 0;
240 530 : mpImp->nViewAspect = embed::Aspects::MSOLE_CONTENT;
241 530 : mpImp->bIsLocked = sal_False;
242 530 : mpImp->bNeedUpdate = sal_False;
243 530 : mpImp->mnGraphicVersion = 0;
244 530 : mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size(8000,7000);
245 530 : }
246 :
247 298 : EmbeddedObjectRef::EmbeddedObjectRef()
248 : {
249 298 : Construct_Impl();
250 298 : }
251 :
252 232 : EmbeddedObjectRef::EmbeddedObjectRef( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Int64 nAspect )
253 : {
254 232 : Construct_Impl();
255 232 : mpImp->nViewAspect = nAspect;
256 232 : mxObj = xObj;
257 232 : mpImp->xListener = EmbedEventListener_Impl::Create( this );
258 232 : }
259 :
260 372 : EmbeddedObjectRef::EmbeddedObjectRef( const EmbeddedObjectRef& rObj )
261 : {
262 372 : mpImp = new EmbeddedObjectRef_Impl;
263 372 : mpImp->pContainer = rObj.mpImp->pContainer;
264 372 : mpImp->nViewAspect = rObj.mpImp->nViewAspect;
265 372 : mpImp->bIsLocked = rObj.mpImp->bIsLocked;
266 372 : mxObj = rObj.mxObj;
267 372 : mpImp->xListener = EmbedEventListener_Impl::Create( this );
268 372 : mpImp->aPersistName = rObj.mpImp->aPersistName;
269 372 : mpImp->aMediaType = rObj.mpImp->aMediaType;
270 372 : mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate;
271 372 : mpImp->aDefaultSizeForChart_In_100TH_MM = rObj.mpImp->aDefaultSizeForChart_In_100TH_MM;
272 :
273 372 : if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate )
274 290 : mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic );
275 : else
276 82 : mpImp->pGraphic = 0;
277 :
278 372 : mpImp->mnGraphicVersion = 0;
279 372 : }
280 :
281 1400 : EmbeddedObjectRef::~EmbeddedObjectRef()
282 : {
283 700 : delete mpImp->pGraphic;
284 700 : Clear();
285 700 : delete mpImp;
286 700 : }
287 :
288 296 : 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 296 : Clear();
293 296 : mpImp->nViewAspect = nAspect;
294 296 : mxObj = xObj;
295 296 : mpImp->xListener = EmbedEventListener_Impl::Create( this );
296 :
297 : //#i103460#
298 296 : 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 296 : }
306 :
307 1082 : void EmbeddedObjectRef::Clear()
308 : {
309 1082 : if ( mxObj.is() && mpImp->xListener )
310 : {
311 698 : mxObj->removeStateChangeListener( mpImp->xListener );
312 :
313 698 : uno::Reference < util::XCloseable > xClose( mxObj, uno::UNO_QUERY );
314 698 : if ( xClose.is() )
315 698 : xClose->removeCloseListener( mpImp->xListener );
316 :
317 698 : uno::Reference < document::XEventBroadcaster > xBrd( mxObj, uno::UNO_QUERY );
318 698 : if ( xBrd.is() )
319 698 : xBrd->removeEventListener( mpImp->xListener );
320 :
321 698 : if ( mpImp->bIsLocked )
322 : {
323 180 : if ( xClose.is() )
324 : {
325 : try
326 : {
327 180 : mxObj->changeState( embed::EmbedStates::LOADED );
328 180 : 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 698 : if ( mpImp->xListener )
342 : {
343 698 : mpImp->xListener->pObject = 0;
344 698 : mpImp->xListener->release();
345 698 : mpImp->xListener = 0;
346 : }
347 :
348 698 : mxObj = 0;
349 698 : mpImp->bNeedUpdate = sal_False;
350 : }
351 :
352 1082 : mpImp->pContainer = 0;
353 1082 : mpImp->bIsLocked = sal_False;
354 1082 : mpImp->bNeedUpdate = sal_False;
355 1082 : }
356 :
357 480 : void EmbeddedObjectRef::AssignToContainer( comphelper::EmbeddedObjectContainer* pContainer, const ::rtl::OUString& rPersistName )
358 : {
359 480 : mpImp->pContainer = pContainer;
360 480 : mpImp->aPersistName = rPersistName;
361 :
362 480 : if ( mpImp->pGraphic && !mpImp->bNeedUpdate && pContainer )
363 290 : SetGraphicToContainer( *mpImp->pGraphic, *pContainer, mpImp->aPersistName, ::rtl::OUString() );
364 480 : }
365 :
366 96 : comphelper::EmbeddedObjectContainer* EmbeddedObjectRef::GetContainer() const
367 : {
368 96 : return mpImp->pContainer;
369 : }
370 :
371 6272 : sal_Int64 EmbeddedObjectRef::GetViewAspect() const
372 : {
373 6272 : return mpImp->nViewAspect;
374 : }
375 :
376 14 : void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect )
377 : {
378 14 : mpImp->nViewAspect = nAspect;
379 14 : }
380 :
381 482 : void EmbeddedObjectRef::Lock( sal_Bool bLock )
382 : {
383 482 : mpImp->bIsLocked = bLock;
384 482 : }
385 :
386 96 : sal_Bool EmbeddedObjectRef::IsLocked() const
387 : {
388 96 : return mpImp->bIsLocked;
389 : }
390 :
391 4546 : void EmbeddedObjectRef::GetReplacement( sal_Bool bUpdate )
392 : {
393 4546 : if ( bUpdate )
394 : {
395 4544 : DELETEZ( mpImp->pGraphic );
396 4544 : mpImp->aMediaType = ::rtl::OUString();
397 4544 : mpImp->pGraphic = new Graphic;
398 4544 : mpImp->mnGraphicVersion++;
399 : }
400 2 : else if ( !mpImp->pGraphic )
401 : {
402 2 : mpImp->pGraphic = new Graphic;
403 2 : mpImp->mnGraphicVersion++;
404 : }
405 : else
406 : {
407 : OSL_FAIL("No update, but replacement exists already!");
408 4546 : return;
409 : }
410 :
411 4546 : SvStream* pGraphicStream = GetGraphicStream( bUpdate );
412 4546 : if ( pGraphicStream )
413 : {
414 4546 : GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
415 4546 : if( mpImp->pGraphic )
416 4546 : rGF.ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
417 4546 : mpImp->mnGraphicVersion++;
418 4546 : delete pGraphicStream;
419 : }
420 : }
421 :
422 450 : Graphic* EmbeddedObjectRef::GetGraphic( ::rtl::OUString* pMediaType ) const
423 : {
424 450 : if ( mpImp->bNeedUpdate )
425 : // bNeedUpdate will be set to false while retrieving new replacement
426 0 : const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_True );
427 450 : else if ( !mpImp->pGraphic )
428 2 : const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_False );
429 :
430 450 : if ( mpImp->pGraphic && pMediaType )
431 0 : *pMediaType = mpImp->aMediaType;
432 450 : return mpImp->pGraphic;
433 : }
434 :
435 202 : Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const
436 : {
437 202 : MapMode aSourceMapMode( MAP_100TH_MM );
438 202 : Size aResult;
439 :
440 202 : 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 202 : awt::Size aSize;
454 :
455 202 : if ( mxObj.is() )
456 : {
457 : try
458 : {
459 202 : aSize = mxObj->getVisualAreaSize( mpImp->nViewAspect );
460 : }
461 0 : catch(const embed::NoVisualAreaSizeException&)
462 : {
463 : }
464 2 : 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 202 : aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) );
472 : }
473 2 : catch(const uno::Exception&)
474 : {
475 : OSL_FAIL( "Can not get the map mode!" );
476 : }
477 : }
478 :
479 202 : if ( !aSize.Height && !aSize.Width )
480 : {
481 2 : aSize.Width = 5000;
482 2 : aSize.Height = 5000;
483 : }
484 :
485 202 : aResult = Size( aSize.Width, aSize.Height );
486 : }
487 :
488 202 : if ( pTargetMapMode )
489 202 : aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode );
490 :
491 202 : 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 8 : void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const ::rtl::OUString& rMediaType )
527 : {
528 8 : if ( mpImp->pGraphic )
529 0 : delete mpImp->pGraphic;
530 8 : mpImp->pGraphic = new Graphic( rGraphic );
531 8 : mpImp->aMediaType = rMediaType;
532 8 : mpImp->mnGraphicVersion++;
533 :
534 8 : if ( mpImp->pContainer )
535 2 : SetGraphicToContainer( rGraphic, *mpImp->pContainer, mpImp->aPersistName, rMediaType );
536 :
537 8 : mpImp->bNeedUpdate = sal_False;
538 8 : }
539 :
540 4546 : 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 4546 : uno::Reference < io::XInputStream > xStream;
545 4546 : 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 2 : xStream = mpImp->pContainer->GetGraphicStream( mxObj, &mpImp->aMediaType );
550 2 : if ( xStream.is() )
551 : {
552 2 : const sal_Int32 nConstBufferSize = 32000;
553 2 : SvStream *pStream = new SvMemoryStream( 32000, 32000 );
554 : try
555 : {
556 2 : sal_Int32 nRead=0;
557 2 : uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
558 2 : do
559 : {
560 2 : nRead = xStream->readBytes ( aSequence, nConstBufferSize );
561 2 : pStream->Write( aSequence.getConstArray(), nRead );
562 : }
563 : while ( nRead == nConstBufferSize );
564 2 : pStream->Seek(0);
565 2 : 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 4544 : 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 4544 : xStream = GetGraphicReplacementStream( mpImp->nViewAspect, mxObj, &mpImp->aMediaType );
581 :
582 4544 : if ( xStream.is() )
583 : {
584 4544 : if ( mpImp->pContainer )
585 0 : mpImp->pContainer->InsertGraphicStream( xStream, mpImp->aPersistName, mpImp->aMediaType );
586 :
587 4544 : SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream );
588 4544 : if ( pResult && bUpdate )
589 4544 : mpImp->bNeedUpdate = sal_False;
590 :
591 4544 : 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 714 : sal_Bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj )
705 : {
706 714 : if ( !xEmbObj.is() )
707 0 : return sal_False;
708 :
709 : try
710 : {
711 714 : if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED )
712 2 : xEmbObj->changeState( embed::EmbedStates::RUNNING );
713 : }
714 4 : catch (const uno::Exception&)
715 : {
716 2 : return sal_False;
717 : }
718 :
719 712 : return sal_True;
720 : }
721 :
722 292 : void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic,
723 : comphelper::EmbeddedObjectContainer& aContainer,
724 : const ::rtl::OUString& aName,
725 : const ::rtl::OUString& aMediaType )
726 : {
727 292 : SvMemoryStream aStream;
728 292 : aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
729 292 : if ( rGraphic.ExportNative( aStream ) )
730 : {
731 292 : aStream.Seek( 0 );
732 :
733 292 : uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream );
734 292 : aContainer.InsertGraphicStream( xStream, aName, aMediaType );
735 : }
736 : else
737 292 : OSL_FAIL( "Export of graphic is failed!\n" );
738 292 : }
739 :
740 4544 : 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 4544 : return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType);
747 : }
748 :
749 80 : void EmbeddedObjectRef::UpdateReplacementOnDemand()
750 : {
751 80 : DELETEZ( mpImp->pGraphic );
752 80 : mpImp->bNeedUpdate = sal_True;
753 80 : mpImp->mnGraphicVersion++;
754 :
755 80 : if( mpImp->pContainer )
756 : {
757 : //remove graphic from container thus a new up to date one is requested on save
758 80 : mpImp->pContainer->RemoveGraphicStream( mpImp->aPersistName );
759 : }
760 80 : }
761 :
762 5000 : 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 5000 : if ( !mxObj.is() )
772 0 : return false;
773 :
774 5000 : SvGlobalName aObjClsId( mxObj->getClassID() );
775 50000 : if(
776 15000 : SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId
777 15000 : || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId
778 15000 : || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId
779 15000 : || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId)
780 : {
781 160 : return sal_True;
782 : }
783 :
784 4840 : return sal_False;
785 : }
786 :
787 : // #i104867#
788 82 : sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const
789 : {
790 82 : 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: */
|