1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svtools.hxx" 30 31 #include <svtools/embedhlp.hxx> 32 #include <svtools/filter.hxx> 33 #include <svtools/svtools.hrc> 34 #include <svtools/svtdata.hxx> 35 36 #include <comphelper/embeddedobjectcontainer.hxx> 37 #include <comphelper/seqstream.hxx> 38 #include <toolkit/helper/vclunohelper.hxx> 39 #include <unotools/ucbstreamhelper.hxx> 40 #include <unotools/streamwrap.hxx> 41 42 #include <tools/globname.hxx> 43 #include <sot/clsids.hxx> 44 #include <com/sun/star/util/XModifyListener.hpp> 45 #ifndef _COM_SUN_STAR_UTIL_XMODIFYiBLE_HPP_ 46 #include <com/sun/star/util/XModifiable.hpp> 47 #endif 48 #include <com/sun/star/embed/EmbedStates.hpp> 49 #include <com/sun/star/embed/EmbedMisc.hpp> 50 #include <com/sun/star/embed/XStateChangeListener.hpp> 51 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp> 52 #include <com/sun/star/util/XModifiable.hpp> 53 #include <com/sun/star/datatransfer/XTransferable.hpp> 54 #include <com/sun/star/chart2/XDefaultSizeTransmitter.hpp> 55 #include <cppuhelper/implbase4.hxx> 56 #include "vcl/svapp.hxx" 57 #include <rtl/logfile.hxx> 58 #include <vos/mutex.hxx> 59 60 using namespace com::sun::star; 61 62 namespace svt 63 { 64 65 class EmbedEventListener_Impl : public ::cppu::WeakImplHelper4 < embed::XStateChangeListener, 66 document::XEventListener, 67 util::XModifyListener, 68 util::XCloseListener > 69 { 70 public: 71 EmbeddedObjectRef* pObject; 72 sal_Int32 nState; 73 74 EmbedEventListener_Impl( EmbeddedObjectRef* p ) : 75 pObject(p) 76 , nState(-1) 77 {} 78 79 static EmbedEventListener_Impl* Create( EmbeddedObjectRef* ); 80 81 virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) 82 throw (embed::WrongStateException, uno::RuntimeException); 83 virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) 84 throw (uno::RuntimeException); 85 virtual void SAL_CALL queryClosing( const lang::EventObject& Source, ::sal_Bool GetsOwnership ) 86 throw (util::CloseVetoException, uno::RuntimeException); 87 virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException); 88 virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException ); 89 virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException ); 90 virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException); 91 }; 92 93 EmbedEventListener_Impl* EmbedEventListener_Impl::Create( EmbeddedObjectRef* p ) 94 { 95 EmbedEventListener_Impl* xRet = new EmbedEventListener_Impl( p ); 96 xRet->acquire(); 97 98 if ( p->GetObject().is() ) 99 { 100 p->GetObject()->addStateChangeListener( xRet ); 101 102 uno::Reference < util::XCloseable > xClose( p->GetObject(), uno::UNO_QUERY ); 103 DBG_ASSERT( xClose.is(), "Object does not support XCloseable!" ); 104 if ( xClose.is() ) 105 xClose->addCloseListener( xRet ); 106 107 uno::Reference < document::XEventBroadcaster > xBrd( p->GetObject(), uno::UNO_QUERY ); 108 if ( xBrd.is() ) 109 xBrd->addEventListener( xRet ); 110 111 xRet->nState = p->GetObject()->getCurrentState(); 112 if ( xRet->nState == embed::EmbedStates::RUNNING ) 113 { 114 uno::Reference < util::XModifiable > xMod( p->GetObject()->getComponent(), uno::UNO_QUERY ); 115 if ( xMod.is() ) 116 // listen for changes in running state (update replacements in case of changes) 117 xMod->addModifyListener( xRet ); 118 } 119 } 120 121 return xRet; 122 } 123 124 void SAL_CALL EmbedEventListener_Impl::changingState( const lang::EventObject&, 125 ::sal_Int32, 126 ::sal_Int32 ) 127 throw ( embed::WrongStateException, 128 uno::RuntimeException ) 129 { 130 } 131 132 void SAL_CALL EmbedEventListener_Impl::stateChanged( const lang::EventObject&, 133 ::sal_Int32 nOldState, 134 ::sal_Int32 nNewState ) 135 throw ( uno::RuntimeException ) 136 { 137 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 138 nState = nNewState; 139 if ( !pObject ) 140 return; 141 142 uno::Reference < util::XModifiable > xMod( pObject->GetObject()->getComponent(), uno::UNO_QUERY ); 143 if ( nNewState == embed::EmbedStates::RUNNING ) 144 { 145 // TODO/LATER: container must be set before! 146 // When is this event created? Who sets the new container when it changed? 147 if( ( pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON ) && nOldState != embed::EmbedStates::LOADED && !pObject->IsChart() ) 148 // get new replacement after deactivation 149 pObject->UpdateReplacement(); 150 151 if( pObject->IsChart() && nOldState == embed::EmbedStates::UI_ACTIVE ) 152 { 153 //create a new metafile replacement when leaving the edit mode 154 //for buggy documents where the old image looks different from the correct one 155 if( xMod.is() && !xMod->isModified() )//in case of modification a new replacement will be requested anyhow 156 pObject->UpdateReplacementOnDemand(); 157 } 158 159 if ( xMod.is() && nOldState == embed::EmbedStates::LOADED ) 160 // listen for changes (update replacements in case of changes) 161 xMod->addModifyListener( this ); 162 } 163 else if ( nNewState == embed::EmbedStates::LOADED ) 164 { 165 // in loaded state we can't listen 166 if ( xMod.is() ) 167 xMod->removeModifyListener( this ); 168 } 169 } 170 171 void SAL_CALL EmbedEventListener_Impl::modified( const lang::EventObject& ) throw (uno::RuntimeException) 172 { 173 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 174 if ( pObject && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON ) 175 { 176 if ( nState == embed::EmbedStates::RUNNING ) 177 { 178 // updates only necessary in non-active states 179 if( pObject->IsChart() ) 180 pObject->UpdateReplacementOnDemand(); 181 else 182 pObject->UpdateReplacement(); 183 } 184 else if ( nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::INPLACE_ACTIVE ) 185 { 186 // in case the object is inplace or UI active the replacement image should be updated on demand 187 pObject->UpdateReplacementOnDemand(); 188 } 189 } 190 } 191 192 void SAL_CALL EmbedEventListener_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException ) 193 { 194 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 195 196 #if 0 197 if ( pObject && aEvent.EventName.equalsAscii("OnSaveDone") || aEvent.EventName.equalsAscii("OnSaveAsDone") ) 198 { 199 // TODO/LATER: container must be set before! 200 // When is this event created? Who sets the new container when it changed? 201 pObject->UpdateReplacement(); 202 } 203 else 204 #endif 205 if ( pObject && aEvent.EventName.equalsAscii("OnVisAreaChanged") && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON && !pObject->IsChart() ) 206 { 207 pObject->UpdateReplacement(); 208 } 209 } 210 211 void SAL_CALL EmbedEventListener_Impl::queryClosing( const lang::EventObject& Source, ::sal_Bool ) 212 throw ( util::CloseVetoException, uno::RuntimeException) 213 { 214 // An embedded object can be shared between several objects (f.e. for undo purposes) 215 // the object will not be closed before the last "customer" is destroyed 216 // Now the EmbeddedObjectRef helper class works like a "lock" on the object 217 if ( pObject && pObject->IsLocked() && Source.Source == pObject->GetObject() ) 218 throw util::CloseVetoException(); 219 } 220 221 void SAL_CALL EmbedEventListener_Impl::notifyClosing( const lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException) 222 { 223 if ( pObject && Source.Source == pObject->GetObject() ) 224 { 225 pObject->Clear(); 226 pObject = 0; 227 } 228 } 229 230 void SAL_CALL EmbedEventListener_Impl::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException ) 231 { 232 if ( pObject && aEvent.Source == pObject->GetObject() ) 233 { 234 pObject->Clear(); 235 pObject = 0; 236 } 237 } 238 239 struct EmbeddedObjectRef_Impl 240 { 241 EmbedEventListener_Impl* xListener; 242 ::rtl::OUString aPersistName; 243 ::rtl::OUString aMediaType; 244 comphelper::EmbeddedObjectContainer* pContainer; 245 Graphic* pGraphic; 246 Graphic* pHCGraphic; 247 sal_Int64 nViewAspect; 248 sal_Bool bIsLocked; 249 sal_Bool bNeedUpdate; 250 251 // #i104867# 252 sal_uInt32 mnGraphicVersion; 253 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 254 }; 255 256 void EmbeddedObjectRef::Construct_Impl() 257 { 258 mpImp = new EmbeddedObjectRef_Impl; 259 mpImp->pContainer = 0; 260 mpImp->pGraphic = 0; 261 mpImp->pHCGraphic = 0; 262 mpImp->nViewAspect = embed::Aspects::MSOLE_CONTENT; 263 mpImp->bIsLocked = sal_False; 264 mpImp->bNeedUpdate = sal_False; 265 mpImp->mnGraphicVersion = 0; 266 mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size(8000,7000); 267 } 268 269 EmbeddedObjectRef::EmbeddedObjectRef() 270 { 271 Construct_Impl(); 272 } 273 274 EmbeddedObjectRef::EmbeddedObjectRef( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect ) 275 { 276 Construct_Impl(); 277 mpImp->nViewAspect = nAspect; 278 mxObj = xObj; 279 mpImp->xListener = EmbedEventListener_Impl::Create( this ); 280 } 281 282 EmbeddedObjectRef::EmbeddedObjectRef( const EmbeddedObjectRef& rObj ) 283 { 284 mpImp = new EmbeddedObjectRef_Impl; 285 mpImp->pContainer = rObj.mpImp->pContainer; 286 mpImp->nViewAspect = rObj.mpImp->nViewAspect; 287 mpImp->bIsLocked = rObj.mpImp->bIsLocked; 288 mxObj = rObj.mxObj; 289 mpImp->xListener = EmbedEventListener_Impl::Create( this ); 290 mpImp->aPersistName = rObj.mpImp->aPersistName; 291 mpImp->aMediaType = rObj.mpImp->aMediaType; 292 mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate; 293 mpImp->aDefaultSizeForChart_In_100TH_MM = rObj.mpImp->aDefaultSizeForChart_In_100TH_MM; 294 295 if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate ) 296 mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic ); 297 else 298 mpImp->pGraphic = 0; 299 300 mpImp->pHCGraphic = 0; 301 mpImp->mnGraphicVersion = 0; 302 } 303 304 EmbeddedObjectRef::~EmbeddedObjectRef() 305 { 306 delete mpImp->pGraphic; 307 if ( mpImp->pHCGraphic ) 308 DELETEZ( mpImp->pHCGraphic ); 309 Clear(); 310 } 311 /* 312 EmbeddedObjectRef& EmbeddedObjectRef::operator = ( const EmbeddedObjectRef& rObj ) 313 { 314 DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" ); 315 316 delete mpImp->pGraphic; 317 if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic ); 318 Clear(); 319 320 mpImp->nViewAspect = rObj.mpImp->nViewAspect; 321 mpImp->bIsLocked = rObj.mpImp->bIsLocked; 322 mxObj = rObj.mxObj; 323 mpImp->xListener = EmbedEventListener_Impl::Create( this ); 324 mpImp->pContainer = rObj.mpImp->pContainer; 325 mpImp->aPersistName = rObj.mpImp->aPersistName; 326 mpImp->aMediaType = rObj.mpImp->aMediaType; 327 mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate; 328 329 if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate ) 330 mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic ); 331 else 332 mpImp->pGraphic = 0; 333 return *this; 334 } 335 */ 336 void EmbeddedObjectRef::Assign( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect ) 337 { 338 DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" ); 339 340 Clear(); 341 mpImp->nViewAspect = nAspect; 342 mxObj = xObj; 343 mpImp->xListener = EmbedEventListener_Impl::Create( this ); 344 345 //#i103460# 346 if ( IsChart() ) 347 { 348 ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( xObj, uno::UNO_QUERY ); 349 DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" ); 350 if( xSizeTransmitter.is() ) 351 xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM ); 352 } 353 } 354 355 void EmbeddedObjectRef::Clear() 356 { 357 if ( mxObj.is() && mpImp->xListener ) 358 { 359 mxObj->removeStateChangeListener( mpImp->xListener ); 360 361 uno::Reference < util::XCloseable > xClose( mxObj, uno::UNO_QUERY ); 362 if ( xClose.is() ) 363 xClose->removeCloseListener( mpImp->xListener ); 364 365 uno::Reference < document::XEventBroadcaster > xBrd( mxObj, uno::UNO_QUERY ); 366 if ( xBrd.is() ) 367 xBrd->removeEventListener( mpImp->xListener ); 368 369 if ( mpImp->bIsLocked ) 370 { 371 if ( xClose.is() ) 372 { 373 try 374 { 375 mxObj->changeState( embed::EmbedStates::LOADED ); 376 xClose->close( sal_True ); 377 } 378 catch ( util::CloseVetoException& ) 379 { 380 // there's still someone who needs the object! 381 } 382 catch ( uno::Exception& ) 383 { 384 OSL_ENSURE( sal_False, "Error on switching of the object to loaded state and closing!\n" ); 385 } 386 } 387 } 388 389 if ( mpImp->xListener ) 390 { 391 mpImp->xListener->pObject = 0; 392 mpImp->xListener->release(); 393 mpImp->xListener = 0; 394 } 395 396 mxObj = 0; 397 mpImp->bNeedUpdate = sal_False; 398 } 399 400 mpImp->pContainer = 0; 401 mpImp->bIsLocked = sal_False; 402 mpImp->bNeedUpdate = sal_False; 403 } 404 405 void EmbeddedObjectRef::AssignToContainer( comphelper::EmbeddedObjectContainer* pContainer, const ::rtl::OUString& rPersistName ) 406 { 407 mpImp->pContainer = pContainer; 408 mpImp->aPersistName = rPersistName; 409 410 if ( mpImp->pGraphic && !mpImp->bNeedUpdate && pContainer ) 411 SetGraphicToContainer( *mpImp->pGraphic, *pContainer, mpImp->aPersistName, ::rtl::OUString() ); 412 } 413 414 comphelper::EmbeddedObjectContainer* EmbeddedObjectRef::GetContainer() const 415 { 416 return mpImp->pContainer; 417 } 418 419 ::rtl::OUString EmbeddedObjectRef::GetPersistName() const 420 { 421 return mpImp->aPersistName; 422 } 423 424 MapUnit EmbeddedObjectRef::GetMapUnit() const 425 { 426 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT ) 427 return VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) ); 428 else 429 // TODO/LATER: currently only CONTENT aspect requires communication with the object 430 return MAP_100TH_MM; 431 } 432 433 sal_Int64 EmbeddedObjectRef::GetViewAspect() const 434 { 435 return mpImp->nViewAspect; 436 } 437 438 void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect ) 439 { 440 mpImp->nViewAspect = nAspect; 441 } 442 443 void EmbeddedObjectRef::Lock( sal_Bool bLock ) 444 { 445 mpImp->bIsLocked = bLock; 446 } 447 448 sal_Bool EmbeddedObjectRef::IsLocked() const 449 { 450 return mpImp->bIsLocked; 451 } 452 453 void EmbeddedObjectRef::GetReplacement( sal_Bool bUpdate ) 454 { 455 if ( bUpdate ) 456 { 457 DELETEZ( mpImp->pGraphic ); 458 mpImp->aMediaType = ::rtl::OUString(); 459 mpImp->pGraphic = new Graphic; 460 if ( mpImp->pHCGraphic ) 461 DELETEZ( mpImp->pHCGraphic ); 462 mpImp->mnGraphicVersion++; 463 } 464 else if ( !mpImp->pGraphic ) 465 { 466 mpImp->pGraphic = new Graphic; 467 mpImp->mnGraphicVersion++; 468 } 469 else 470 { 471 DBG_ERROR("No update, but replacement exists already!"); 472 return; 473 } 474 475 SvStream* pGraphicStream = GetGraphicStream( bUpdate ); 476 if ( pGraphicStream ) 477 { 478 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); 479 if( mpImp->pGraphic ) 480 pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ); 481 mpImp->mnGraphicVersion++; 482 delete pGraphicStream; 483 } 484 } 485 486 Graphic* EmbeddedObjectRef::GetGraphic( ::rtl::OUString* pMediaType ) const 487 { 488 if ( mpImp->bNeedUpdate ) 489 // bNeedUpdate will be set to false while retrieving new replacement 490 const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_True ); 491 else if ( !mpImp->pGraphic ) 492 const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_False ); 493 494 if ( mpImp->pGraphic && pMediaType ) 495 *pMediaType = mpImp->aMediaType; 496 return mpImp->pGraphic; 497 } 498 499 Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const 500 { 501 MapMode aSourceMapMode( MAP_100TH_MM ); 502 Size aResult; 503 504 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_ICON ) 505 { 506 Graphic* pGraphic = GetGraphic(); 507 if ( pGraphic ) 508 { 509 aSourceMapMode = pGraphic->GetPrefMapMode(); 510 aResult = pGraphic->GetPrefSize(); 511 } 512 else 513 aResult = Size( 2500, 2500 ); 514 } 515 else 516 { 517 awt::Size aSize; 518 519 if ( mxObj.is() ) 520 { 521 try 522 { 523 aSize = mxObj->getVisualAreaSize( mpImp->nViewAspect ); 524 } 525 catch( embed::NoVisualAreaSizeException& ) 526 { 527 } 528 catch( uno::Exception& ) 529 { 530 OSL_ENSURE( sal_False, "Something went wrong on getting of the size of the object!" ); 531 } 532 533 try 534 { 535 aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) ); 536 } 537 catch( uno::Exception ) 538 { 539 OSL_ENSURE( sal_False, "Can not get the map mode!" ); 540 } 541 } 542 543 if ( !aSize.Height && !aSize.Width ) 544 { 545 aSize.Width = 5000; 546 aSize.Height = 5000; 547 } 548 549 aResult = Size( aSize.Width, aSize.Height ); 550 } 551 552 if ( pTargetMapMode ) 553 aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode ); 554 555 return aResult; 556 } 557 558 Graphic* EmbeddedObjectRef::GetHCGraphic() const 559 { 560 if ( !mpImp->pHCGraphic ) 561 { 562 uno::Reference< io::XInputStream > xInStream; 563 try 564 { 565 // if the object needs size on load, that means that it is not our object 566 // currently the HC mode is supported only for OOo own objects so the following 567 // check is used as an optimization 568 // TODO/LATER: shouldn't there be a special status flag to detect alien implementation? 569 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT 570 && mxObj.is() && !( mxObj->getStatus( mpImp->nViewAspect ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD ) ) 571 { 572 // TODO/LATER: optimization, it makes no sence to do it for OLE objects 573 if ( mxObj->getCurrentState() == embed::EmbedStates::LOADED ) 574 mxObj->changeState( embed::EmbedStates::RUNNING ); 575 576 // TODO: return for the aspect of the document 577 embed::VisualRepresentation aVisualRepresentation; 578 uno::Reference< datatransfer::XTransferable > xTransferable( mxObj->getComponent(), uno::UNO_QUERY ); 579 if ( !xTransferable.is() ) 580 throw uno::RuntimeException(); 581 582 datatransfer::DataFlavor aDataFlavor( 583 ::rtl::OUString::createFromAscii( 584 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" ), 585 ::rtl::OUString::createFromAscii( "GDIMetaFile" ), 586 ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); 587 588 uno::Sequence < sal_Int8 > aSeq; 589 if ( ( xTransferable->getTransferData( aDataFlavor ) >>= aSeq ) && aSeq.getLength() ) 590 xInStream = new ::comphelper::SequenceInputStream( aSeq ); 591 } 592 } 593 catch ( uno::Exception& ) 594 { 595 } 596 597 if ( xInStream.is() ) 598 { 599 SvStream* pStream = NULL; 600 pStream = ::utl::UcbStreamHelper::CreateStream( xInStream ); 601 if ( pStream ) 602 { 603 if ( !pStream->GetError() ) 604 { 605 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); 606 Graphic* pGraphic = new Graphic(); 607 if ( pGF->ImportGraphic( *pGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW ) == 0 ) 608 mpImp->pHCGraphic = pGraphic; 609 else 610 delete pGraphic; 611 mpImp->mnGraphicVersion++; 612 } 613 614 delete pStream; 615 } 616 } 617 } 618 619 return mpImp->pHCGraphic; 620 } 621 622 void EmbeddedObjectRef::SetGraphicStream( const uno::Reference< io::XInputStream >& xInGrStream, 623 const ::rtl::OUString& rMediaType ) 624 { 625 if ( mpImp->pGraphic ) 626 delete mpImp->pGraphic; 627 mpImp->pGraphic = new Graphic(); 628 mpImp->aMediaType = rMediaType; 629 if ( mpImp->pHCGraphic ) 630 DELETEZ( mpImp->pHCGraphic ); 631 mpImp->mnGraphicVersion++; 632 633 SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( xInGrStream ); 634 635 if ( pGraphicStream ) 636 { 637 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); 638 pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ); 639 mpImp->mnGraphicVersion++; 640 641 if ( mpImp->pContainer ) 642 { 643 pGraphicStream->Seek( 0 ); 644 uno::Reference< io::XInputStream > xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream ); 645 646 mpImp->pContainer->InsertGraphicStream( xInSeekGrStream, mpImp->aPersistName, rMediaType ); 647 } 648 649 delete pGraphicStream; 650 } 651 652 mpImp->bNeedUpdate = sal_False; 653 654 } 655 656 void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const ::rtl::OUString& rMediaType ) 657 { 658 if ( mpImp->pGraphic ) 659 delete mpImp->pGraphic; 660 mpImp->pGraphic = new Graphic( rGraphic ); 661 mpImp->aMediaType = rMediaType; 662 if ( mpImp->pHCGraphic ) 663 DELETEZ( mpImp->pHCGraphic ); 664 mpImp->mnGraphicVersion++; 665 666 if ( mpImp->pContainer ) 667 SetGraphicToContainer( rGraphic, *mpImp->pContainer, mpImp->aPersistName, rMediaType ); 668 669 mpImp->bNeedUpdate = sal_False; 670 } 671 672 SvStream* EmbeddedObjectRef::GetGraphicStream( sal_Bool bUpdate ) const 673 { 674 RTL_LOGFILE_CONTEXT( aLog, "svtools (mv76033) svt::EmbeddedObjectRef::GetGraphicStream" ); 675 DBG_ASSERT( bUpdate || mpImp->pContainer, "Can't retrieve current graphic!" ); 676 uno::Reference < io::XInputStream > xStream; 677 if ( mpImp->pContainer && !bUpdate ) 678 { 679 RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from container" ); 680 // try to get graphic stream from container storage 681 xStream = mpImp->pContainer->GetGraphicStream( mxObj, &mpImp->aMediaType ); 682 if ( xStream.is() ) 683 { 684 const sal_Int32 nConstBufferSize = 32000; 685 SvStream *pStream = new SvMemoryStream( 32000, 32000 ); 686 sal_Int32 nRead=0; 687 uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize ); 688 do 689 { 690 nRead = xStream->readBytes ( aSequence, nConstBufferSize ); 691 pStream->Write( aSequence.getConstArray(), nRead ); 692 } 693 while ( nRead == nConstBufferSize ); 694 pStream->Seek(0); 695 return pStream; 696 } 697 } 698 699 if ( !xStream.is() ) 700 { 701 RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from object" ); 702 // update wanted or no stream in container storage available 703 xStream = GetGraphicReplacementStream( mpImp->nViewAspect, mxObj, &mpImp->aMediaType ); 704 705 if ( xStream.is() ) 706 { 707 if ( mpImp->pContainer ) 708 mpImp->pContainer->InsertGraphicStream( xStream, mpImp->aPersistName, mpImp->aMediaType ); 709 710 SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream ); 711 if ( pResult && bUpdate ) 712 mpImp->bNeedUpdate = sal_False; 713 714 return pResult; 715 } 716 } 717 718 return NULL; 719 } 720 721 void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const String &rText, OutputDevice *pOut ) 722 { 723 MapMode aMM( MAP_APPFONT ); 724 Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL ); 725 Font aFnt( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Helvetica" ) ), aAppFontSz ); 726 aFnt.SetTransparent( sal_True ); 727 aFnt.SetColor( Color( COL_LIGHTRED ) ); 728 aFnt.SetWeight( WEIGHT_BOLD ); 729 aFnt.SetFamily( FAMILY_SWISS ); 730 731 pOut->Push(); 732 pOut->SetBackground(); 733 pOut->SetFont( aFnt ); 734 735 Point aPt; 736 // Nun den Text so skalieren, dass er in das Rect passt. 737 // Wir fangen mit der Defaultsize an und gehen 1-AppFont runter 738 for( sal_uInt16 i = 8; i > 2; i-- ) 739 { 740 aPt.X() = (rRect.GetWidth() - pOut->GetTextWidth( rText )) / 2; 741 aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2; 742 743 sal_Bool bTiny = sal_False; 744 if( aPt.X() < 0 ) bTiny = sal_True, aPt.X() = 0; 745 if( aPt.Y() < 0 ) bTiny = sal_True, aPt.Y() = 0; 746 if( bTiny ) 747 { 748 // heruntergehen bei kleinen Bildern 749 aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) ); 750 pOut->SetFont( aFnt ); 751 } 752 else 753 break; 754 } 755 756 Bitmap aBmp( SvtResId( BMP_PLUGIN ) ); 757 long nHeight = rRect.GetHeight() - pOut->GetTextHeight(); 758 long nWidth = rRect.GetWidth(); 759 if( nHeight > 0 ) 760 { 761 aPt.Y() = nHeight; 762 Point aP = rRect.TopLeft(); 763 Size aBmpSize = aBmp.GetSizePixel(); 764 // Bitmap einpassen 765 if( nHeight * 10 / nWidth 766 > aBmpSize.Height() * 10 / aBmpSize.Width() ) 767 { 768 // nach der Breite ausrichten 769 // Proportion beibehalten 770 long nH = nWidth * aBmpSize.Height() / aBmpSize.Width(); 771 // zentrieren 772 aP.Y() += (nHeight - nH) / 2; 773 nHeight = nH; 774 } 775 else 776 { 777 // nach der H"ohe ausrichten 778 // Proportion beibehalten 779 long nW = nHeight * aBmpSize.Width() / aBmpSize.Height(); 780 // zentrieren 781 aP.X() += (nWidth - nW) / 2; 782 nWidth = nW; 783 } 784 785 pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp ); 786 } 787 788 pOut->IntersectClipRegion( rRect ); 789 aPt += rRect.TopLeft(); 790 pOut->DrawText( aPt, rText ); 791 pOut->Pop(); 792 } 793 794 void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut ) 795 { 796 GDIMetaFile * pMtf = pOut->GetConnectMetaFile(); 797 if( pMtf && pMtf->IsRecord() ) 798 return; 799 800 pOut->Push(); 801 pOut->SetLineColor( Color( COL_BLACK ) ); 802 803 Size aPixSize = pOut->LogicToPixel( rRect.GetSize() ); 804 aPixSize.Width() -= 1; 805 aPixSize.Height() -= 1; 806 Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() ); 807 sal_Int32 nMax = aPixSize.Width() + aPixSize.Height(); 808 for( sal_Int32 i = 5; i < nMax; i += 5 ) 809 { 810 Point a1( aPixViewPos ), a2( aPixViewPos ); 811 if( i > aPixSize.Width() ) 812 a1 += Point( aPixSize.Width(), i - aPixSize.Width() ); 813 else 814 a1 += Point( i, 0 ); 815 if( i > aPixSize.Height() ) 816 a2 += Point( i - aPixSize.Height(), aPixSize.Height() ); 817 else 818 a2 += Point( 0, i ); 819 820 pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) ); 821 } 822 823 pOut->Pop(); 824 825 } 826 827 sal_Bool EmbeddedObjectRef::TryRunningState() 828 { 829 return TryRunningState( mxObj ); 830 } 831 832 sal_Bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj ) 833 { 834 if ( !xEmbObj.is() ) 835 return sal_False; 836 837 try 838 { 839 if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED ) 840 xEmbObj->changeState( embed::EmbedStates::RUNNING ); 841 } 842 catch ( uno::Exception& ) 843 { 844 return sal_False; 845 } 846 847 return sal_True; 848 } 849 850 void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic, 851 comphelper::EmbeddedObjectContainer& aContainer, 852 const ::rtl::OUString& aName, 853 const ::rtl::OUString& aMediaType ) 854 { 855 SvMemoryStream aStream; 856 aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT ); 857 if ( rGraphic.ExportNative( aStream ) ) 858 { 859 aStream.Seek( 0 ); 860 861 uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream ); 862 aContainer.InsertGraphicStream( xStream, aName, aMediaType ); 863 } 864 else 865 OSL_ENSURE( sal_False, "Export of graphic is failed!\n" ); 866 } 867 868 sal_Bool EmbeddedObjectRef::ObjectIsModified( const uno::Reference< embed::XEmbeddedObject >& xObj ) 869 throw( uno::Exception ) 870 { 871 sal_Bool bResult = sal_False; 872 873 sal_Int32 nState = xObj->getCurrentState(); 874 if ( nState != embed::EmbedStates::LOADED && nState != embed::EmbedStates::RUNNING ) 875 { 876 // the object is active so if the model is modified the replacement 877 // should be retrieved from the object 878 uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY ); 879 if ( xModifiable.is() ) 880 bResult = xModifiable->isModified(); 881 } 882 883 return bResult; 884 } 885 886 uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream( 887 sal_Int64 nViewAspect, 888 const uno::Reference< embed::XEmbeddedObject >& xObj, 889 ::rtl::OUString* pMediaType ) 890 throw() 891 { 892 return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType); 893 } 894 895 void EmbeddedObjectRef::UpdateReplacementOnDemand() 896 { 897 DELETEZ( mpImp->pGraphic ); 898 mpImp->bNeedUpdate = sal_True; 899 if ( mpImp->pHCGraphic ) 900 DELETEZ( mpImp->pHCGraphic ); 901 mpImp->mnGraphicVersion++; 902 903 if( mpImp->pContainer ) 904 { 905 //remove graphic from container thus a new up to date one is requested on save 906 mpImp->pContainer->RemoveGraphicStream( mpImp->aPersistName ); 907 } 908 } 909 910 sal_Bool EmbeddedObjectRef::IsChart() const 911 { 912 //todo maybe for 3.0: 913 //if the changes work good for chart 914 //we should apply them for all own ole objects 915 916 //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary 917 //as this call can be very expensive and does block the user interface as long at it takes 918 919 if ( !mxObj.is() ) 920 return false; 921 922 SvGlobalName aObjClsId( mxObj->getClassID() ); 923 if( 924 SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId 925 || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId 926 || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId 927 || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId) 928 { 929 return sal_True; 930 } 931 932 return sal_False; 933 } 934 935 // #i104867# 936 sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const 937 { 938 return mpImp->mnGraphicVersion; 939 } 940 941 void EmbeddedObjectRef::SetDefaultSizeForChart( const Size& rSizeIn_100TH_MM ) 942 { 943 //#i103460# charts do not necessaryly have an own size within ODF files, 944 //for this case they need to use the size settings from the surrounding frame, 945 //which is made available with this method 946 947 mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size( rSizeIn_100TH_MM.getWidth(), rSizeIn_100TH_MM.getHeight() ); 948 949 ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( mxObj, uno::UNO_QUERY ); 950 DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" ); 951 if( xSizeTransmitter.is() ) 952 xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM ); 953 } 954 955 } // namespace svt 956 957