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