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