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 try 486 { 487 if ( mpImp->bNeedUpdate ) 488 // bNeedUpdate will be set to false while retrieving new replacement 489 const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_True ); 490 else if ( !mpImp->pGraphic ) 491 const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_False ); 492 } 493 catch( uno::Exception& ) 494 { 495 OSL_ENSURE( sal_False, "Something went wrong on getting the graphic!" ); 496 } 497 498 if ( mpImp->pGraphic && pMediaType ) 499 *pMediaType = mpImp->aMediaType; 500 return mpImp->pGraphic; 501 } 502 503 Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const 504 { 505 MapMode aSourceMapMode( MAP_100TH_MM ); 506 Size aResult; 507 508 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_ICON ) 509 { 510 Graphic* pGraphic = GetGraphic(); 511 if ( pGraphic ) 512 { 513 aSourceMapMode = pGraphic->GetPrefMapMode(); 514 aResult = pGraphic->GetPrefSize(); 515 } 516 else 517 aResult = Size( 2500, 2500 ); 518 } 519 else 520 { 521 awt::Size aSize; 522 523 if ( mxObj.is() ) 524 { 525 try 526 { 527 aSize = mxObj->getVisualAreaSize( mpImp->nViewAspect ); 528 } 529 catch( embed::NoVisualAreaSizeException& ) 530 { 531 } 532 catch( uno::Exception& ) 533 { 534 OSL_ENSURE( sal_False, "Something went wrong on getting of the size of the object!" ); 535 } 536 537 try 538 { 539 aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) ); 540 } 541 catch( uno::Exception ) 542 { 543 OSL_ENSURE( sal_False, "Can not get the map mode!" ); 544 } 545 } 546 547 if ( !aSize.Height && !aSize.Width ) 548 { 549 aSize.Width = 5000; 550 aSize.Height = 5000; 551 } 552 553 aResult = Size( aSize.Width, aSize.Height ); 554 } 555 556 if ( pTargetMapMode ) 557 aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode ); 558 559 return aResult; 560 } 561 562 Graphic* EmbeddedObjectRef::GetHCGraphic() const 563 { 564 if ( !mpImp->pHCGraphic ) 565 { 566 uno::Reference< io::XInputStream > xInStream; 567 try 568 { 569 // if the object needs size on load, that means that it is not our object 570 // currently the HC mode is supported only for OOo own objects so the following 571 // check is used as an optimization 572 // TODO/LATER: shouldn't there be a special status flag to detect alien implementation? 573 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT 574 && mxObj.is() && !( mxObj->getStatus( mpImp->nViewAspect ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD ) ) 575 { 576 // TODO/LATER: optimization, it makes no sence to do it for OLE objects 577 if ( mxObj->getCurrentState() == embed::EmbedStates::LOADED ) 578 mxObj->changeState( embed::EmbedStates::RUNNING ); 579 580 // TODO: return for the aspect of the document 581 embed::VisualRepresentation aVisualRepresentation; 582 uno::Reference< datatransfer::XTransferable > xTransferable( mxObj->getComponent(), uno::UNO_QUERY ); 583 if ( !xTransferable.is() ) 584 throw uno::RuntimeException(); 585 586 datatransfer::DataFlavor aDataFlavor( 587 ::rtl::OUString::createFromAscii( 588 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" ), 589 ::rtl::OUString::createFromAscii( "GDIMetaFile" ), 590 ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); 591 592 uno::Sequence < sal_Int8 > aSeq; 593 if ( ( xTransferable->getTransferData( aDataFlavor ) >>= aSeq ) && aSeq.getLength() ) 594 xInStream = new ::comphelper::SequenceInputStream( aSeq ); 595 } 596 } 597 catch ( uno::Exception& ) 598 { 599 OSL_ENSURE( sal_False, "Something went wrong on getting the high contrast graphic!" ); 600 } 601 602 if ( xInStream.is() ) 603 { 604 SvStream* pStream = NULL; 605 pStream = ::utl::UcbStreamHelper::CreateStream( xInStream ); 606 if ( pStream ) 607 { 608 if ( !pStream->GetError() ) 609 { 610 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); 611 Graphic* pGraphic = new Graphic(); 612 if ( pGF->ImportGraphic( *pGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW ) == 0 ) 613 mpImp->pHCGraphic = pGraphic; 614 else 615 delete pGraphic; 616 mpImp->mnGraphicVersion++; 617 } 618 619 delete pStream; 620 } 621 } 622 } 623 624 return mpImp->pHCGraphic; 625 } 626 627 void EmbeddedObjectRef::SetGraphicStream( const uno::Reference< io::XInputStream >& xInGrStream, 628 const ::rtl::OUString& rMediaType ) 629 { 630 if ( mpImp->pGraphic ) 631 delete mpImp->pGraphic; 632 mpImp->pGraphic = new Graphic(); 633 mpImp->aMediaType = rMediaType; 634 if ( mpImp->pHCGraphic ) 635 DELETEZ( mpImp->pHCGraphic ); 636 mpImp->mnGraphicVersion++; 637 638 SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( xInGrStream ); 639 640 if ( pGraphicStream ) 641 { 642 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); 643 pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ); 644 mpImp->mnGraphicVersion++; 645 646 if ( mpImp->pContainer ) 647 { 648 pGraphicStream->Seek( 0 ); 649 uno::Reference< io::XInputStream > xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream ); 650 651 mpImp->pContainer->InsertGraphicStream( xInSeekGrStream, mpImp->aPersistName, rMediaType ); 652 } 653 654 delete pGraphicStream; 655 } 656 657 mpImp->bNeedUpdate = sal_False; 658 659 } 660 661 void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const ::rtl::OUString& rMediaType ) 662 { 663 if ( mpImp->pGraphic ) 664 delete mpImp->pGraphic; 665 mpImp->pGraphic = new Graphic( rGraphic ); 666 mpImp->aMediaType = rMediaType; 667 if ( mpImp->pHCGraphic ) 668 DELETEZ( mpImp->pHCGraphic ); 669 mpImp->mnGraphicVersion++; 670 671 if ( mpImp->pContainer ) 672 SetGraphicToContainer( rGraphic, *mpImp->pContainer, mpImp->aPersistName, rMediaType ); 673 674 mpImp->bNeedUpdate = sal_False; 675 } 676 677 SvStream* EmbeddedObjectRef::GetGraphicStream( sal_Bool bUpdate ) const 678 { 679 RTL_LOGFILE_CONTEXT( aLog, "svtools (mv76033) svt::EmbeddedObjectRef::GetGraphicStream" ); 680 DBG_ASSERT( bUpdate || mpImp->pContainer, "Can't retrieve current graphic!" ); 681 uno::Reference < io::XInputStream > xStream; 682 if ( mpImp->pContainer && !bUpdate ) 683 { 684 RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from container" ); 685 // try to get graphic stream from container storage 686 xStream = mpImp->pContainer->GetGraphicStream( mxObj, &mpImp->aMediaType ); 687 if ( xStream.is() ) 688 { 689 const sal_Int32 nConstBufferSize = 32000; 690 SvStream *pStream = new SvMemoryStream( 32000, 32000 ); 691 sal_Int32 nRead=0; 692 uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize ); 693 do 694 { 695 nRead = xStream->readBytes ( aSequence, nConstBufferSize ); 696 pStream->Write( aSequence.getConstArray(), nRead ); 697 } 698 while ( nRead == nConstBufferSize ); 699 pStream->Seek(0); 700 return pStream; 701 } 702 } 703 704 if ( !xStream.is() ) 705 { 706 RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from object" ); 707 // update wanted or no stream in container storage available 708 xStream = GetGraphicReplacementStream( mpImp->nViewAspect, mxObj, &mpImp->aMediaType ); 709 710 if ( xStream.is() ) 711 { 712 if ( mpImp->pContainer ) 713 mpImp->pContainer->InsertGraphicStream( xStream, mpImp->aPersistName, mpImp->aMediaType ); 714 715 SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream ); 716 if ( pResult && bUpdate ) 717 mpImp->bNeedUpdate = sal_False; 718 719 return pResult; 720 } 721 } 722 723 return NULL; 724 } 725 726 void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const String &rText, OutputDevice *pOut ) 727 { 728 MapMode aMM( MAP_APPFONT ); 729 Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL ); 730 Font aFnt( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Helvetica" ) ), aAppFontSz ); 731 aFnt.SetTransparent( sal_True ); 732 aFnt.SetColor( Color( COL_LIGHTRED ) ); 733 aFnt.SetWeight( WEIGHT_BOLD ); 734 aFnt.SetFamily( FAMILY_SWISS ); 735 736 pOut->Push(); 737 pOut->SetBackground(); 738 pOut->SetFont( aFnt ); 739 740 Point aPt; 741 // Nun den Text so skalieren, dass er in das Rect passt. 742 // Wir fangen mit der Defaultsize an und gehen 1-AppFont runter 743 for( sal_uInt16 i = 8; i > 2; i-- ) 744 { 745 aPt.X() = (rRect.GetWidth() - pOut->GetTextWidth( rText )) / 2; 746 aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2; 747 748 sal_Bool bTiny = sal_False; 749 if( aPt.X() < 0 ) bTiny = sal_True, aPt.X() = 0; 750 if( aPt.Y() < 0 ) bTiny = sal_True, aPt.Y() = 0; 751 if( bTiny ) 752 { 753 // heruntergehen bei kleinen Bildern 754 aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) ); 755 pOut->SetFont( aFnt ); 756 } 757 else 758 break; 759 } 760 761 Bitmap aBmp( SvtResId( BMP_PLUGIN ) ); 762 long nHeight = rRect.GetHeight() - pOut->GetTextHeight(); 763 long nWidth = rRect.GetWidth(); 764 if( nHeight > 0 ) 765 { 766 aPt.Y() = nHeight; 767 Point aP = rRect.TopLeft(); 768 Size aBmpSize = aBmp.GetSizePixel(); 769 // Bitmap einpassen 770 if( nHeight * 10 / nWidth 771 > aBmpSize.Height() * 10 / aBmpSize.Width() ) 772 { 773 // nach der Breite ausrichten 774 // Proportion beibehalten 775 long nH = nWidth * aBmpSize.Height() / aBmpSize.Width(); 776 // zentrieren 777 aP.Y() += (nHeight - nH) / 2; 778 nHeight = nH; 779 } 780 else 781 { 782 // nach der H"ohe ausrichten 783 // Proportion beibehalten 784 long nW = nHeight * aBmpSize.Width() / aBmpSize.Height(); 785 // zentrieren 786 aP.X() += (nWidth - nW) / 2; 787 nWidth = nW; 788 } 789 790 pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp ); 791 } 792 793 pOut->IntersectClipRegion( rRect ); 794 aPt += rRect.TopLeft(); 795 pOut->DrawText( aPt, rText ); 796 pOut->Pop(); 797 } 798 799 void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut ) 800 { 801 GDIMetaFile * pMtf = pOut->GetConnectMetaFile(); 802 if( pMtf && pMtf->IsRecord() ) 803 return; 804 805 pOut->Push(); 806 pOut->SetLineColor( Color( COL_BLACK ) ); 807 808 Size aPixSize = pOut->LogicToPixel( rRect.GetSize() ); 809 aPixSize.Width() -= 1; 810 aPixSize.Height() -= 1; 811 Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() ); 812 sal_Int32 nMax = aPixSize.Width() + aPixSize.Height(); 813 for( sal_Int32 i = 5; i < nMax; i += 5 ) 814 { 815 Point a1( aPixViewPos ), a2( aPixViewPos ); 816 if( i > aPixSize.Width() ) 817 a1 += Point( aPixSize.Width(), i - aPixSize.Width() ); 818 else 819 a1 += Point( i, 0 ); 820 if( i > aPixSize.Height() ) 821 a2 += Point( i - aPixSize.Height(), aPixSize.Height() ); 822 else 823 a2 += Point( 0, i ); 824 825 pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) ); 826 } 827 828 pOut->Pop(); 829 830 } 831 832 sal_Bool EmbeddedObjectRef::TryRunningState() 833 { 834 return TryRunningState( mxObj ); 835 } 836 837 sal_Bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj ) 838 { 839 if ( !xEmbObj.is() ) 840 return sal_False; 841 842 try 843 { 844 if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED ) 845 xEmbObj->changeState( embed::EmbedStates::RUNNING ); 846 } 847 catch ( uno::Exception& ) 848 { 849 return sal_False; 850 } 851 852 return sal_True; 853 } 854 855 void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic, 856 comphelper::EmbeddedObjectContainer& aContainer, 857 const ::rtl::OUString& aName, 858 const ::rtl::OUString& aMediaType ) 859 { 860 SvMemoryStream aStream; 861 aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT ); 862 if ( rGraphic.ExportNative( aStream ) ) 863 { 864 aStream.Seek( 0 ); 865 866 uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream ); 867 aContainer.InsertGraphicStream( xStream, aName, aMediaType ); 868 } 869 else 870 OSL_ENSURE( sal_False, "Export of graphic is failed!\n" ); 871 } 872 873 sal_Bool EmbeddedObjectRef::ObjectIsModified( const uno::Reference< embed::XEmbeddedObject >& xObj ) 874 throw( uno::Exception ) 875 { 876 sal_Bool bResult = sal_False; 877 878 sal_Int32 nState = xObj->getCurrentState(); 879 if ( nState != embed::EmbedStates::LOADED && nState != embed::EmbedStates::RUNNING ) 880 { 881 // the object is active so if the model is modified the replacement 882 // should be retrieved from the object 883 uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY ); 884 if ( xModifiable.is() ) 885 bResult = xModifiable->isModified(); 886 } 887 888 return bResult; 889 } 890 891 uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream( 892 sal_Int64 nViewAspect, 893 const uno::Reference< embed::XEmbeddedObject >& xObj, 894 ::rtl::OUString* pMediaType ) 895 throw() 896 { 897 return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType); 898 } 899 900 void EmbeddedObjectRef::UpdateReplacementOnDemand() 901 { 902 DELETEZ( mpImp->pGraphic ); 903 mpImp->bNeedUpdate = sal_True; 904 if ( mpImp->pHCGraphic ) 905 DELETEZ( mpImp->pHCGraphic ); 906 mpImp->mnGraphicVersion++; 907 908 if( mpImp->pContainer ) 909 { 910 //remove graphic from container thus a new up to date one is requested on save 911 mpImp->pContainer->RemoveGraphicStream( mpImp->aPersistName ); 912 } 913 } 914 915 sal_Bool EmbeddedObjectRef::IsChart() const 916 { 917 //todo maybe for 3.0: 918 //if the changes work good for chart 919 //we should apply them for all own ole objects 920 921 //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary 922 //as this call can be very expensive and does block the user interface as long at it takes 923 924 if ( !mxObj.is() ) 925 return false; 926 927 SvGlobalName aObjClsId( mxObj->getClassID() ); 928 if( 929 SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId 930 || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId 931 || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId 932 || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId) 933 { 934 return sal_True; 935 } 936 937 return sal_False; 938 } 939 940 // #i104867# 941 sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const 942 { 943 return mpImp->mnGraphicVersion; 944 } 945 946 void EmbeddedObjectRef::SetDefaultSizeForChart( const Size& rSizeIn_100TH_MM ) 947 { 948 //#i103460# charts do not necessaryly have an own size within ODF files, 949 //for this case they need to use the size settings from the surrounding frame, 950 //which is made available with this method 951 952 mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size( rSizeIn_100TH_MM.getWidth(), rSizeIn_100TH_MM.getHeight() ); 953 954 ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( mxObj, uno::UNO_QUERY ); 955 DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" ); 956 if( xSizeTransmitter.is() ) 957 xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM ); 958 } 959 960 } // namespace svt 961 962