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_embeddedobj.hxx" 26 #include <com/sun/star/lang/DisposedException.hpp> 27 #include <com/sun/star/embed/EmbedStates.hpp> 28 #include <com/sun/star/embed/EmbedMapUnits.hpp> 29 #include <com/sun/star/embed/EmbedMisc.hpp> 30 #include <com/sun/star/embed/Aspects.hpp> 31 #include <com/sun/star/io/XSeekable.hpp> 32 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp> 33 34 #include <rtl/logfile.hxx> 35 36 #include <oleembobj.hxx> 37 #include <olecomponent.hxx> 38 #include <comphelper/mimeconfighelper.hxx> 39 #include <comphelper/seqstream.hxx> 40 41 using namespace ::com::sun::star; 42 using namespace ::comphelper; 43 44 embed::VisualRepresentation OleEmbeddedObject::GetVisualRepresentationInNativeFormat_Impl( 45 const uno::Reference< io::XStream > xCachedVisRepr ) 46 throw ( uno::Exception ) 47 { 48 embed::VisualRepresentation aVisualRepr; 49 50 // TODO: detect the format in the future for now use workaround 51 uno::Reference< io::XInputStream > xInStream = xCachedVisRepr->getInputStream(); 52 uno::Reference< io::XSeekable > xSeekable( xCachedVisRepr, uno::UNO_QUERY ); 53 if ( !xInStream.is() || !xSeekable.is() ) 54 throw uno::RuntimeException(); 55 56 uno::Sequence< sal_Int8 > aSeq( 2 ); 57 xInStream->readBytes( aSeq, 2 ); 58 xSeekable->seek( 0 ); 59 if ( aSeq.getLength() == 2 && aSeq[0] == 'B' && aSeq[1] == 'M' ) 60 { 61 // it's a bitmap 62 aVisualRepr.Flavor = datatransfer::DataFlavor( 63 ::rtl::OUString::createFromAscii( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" ), 64 ::rtl::OUString::createFromAscii( "Bitmap" ), 65 ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); 66 } 67 else 68 { 69 // it's a metafile 70 aVisualRepr.Flavor = datatransfer::DataFlavor( 71 ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ), 72 ::rtl::OUString::createFromAscii( "Windows Metafile" ), 73 ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); 74 } 75 76 sal_Int32 nStreamLength = (sal_Int32)xSeekable->getLength(); 77 uno::Sequence< sal_Int8 > aRepresent( nStreamLength ); 78 xInStream->readBytes( aRepresent, nStreamLength ); 79 aVisualRepr.Data <<= aRepresent; 80 81 return aVisualRepr; 82 } 83 84 void SAL_CALL OleEmbeddedObject::setVisualAreaSize( sal_Int64 nAspect, const awt::Size& aSize ) 85 throw ( lang::IllegalArgumentException, 86 embed::WrongStateException, 87 uno::Exception, 88 uno::RuntimeException ) 89 { 90 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::setVisualAreaSize" ); 91 92 // begin wrapping related part ==================== 93 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; 94 if ( xWrappedObject.is() ) 95 { 96 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 97 xWrappedObject->setVisualAreaSize( nAspect, aSize ); 98 return; 99 } 100 // end wrapping related part ==================== 101 102 ::osl::ResettableMutexGuard aGuard( m_aMutex ); 103 if ( m_bDisposed ) 104 throw lang::DisposedException(); // TODO 105 106 OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); 107 if ( nAspect == embed::Aspects::MSOLE_ICON ) 108 // no representation can be retrieved 109 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), 110 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 111 112 if ( m_nObjectState == -1 ) 113 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), 114 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 115 116 #ifdef WNT 117 // RECOMPOSE_ON_RESIZE misc flag means that the object has to be switched to running state on resize. 118 // SetExtent() is called only for objects that require it, 119 // it should not be called for MSWord documents to workaround problem i49369 120 // If cached size is not set, that means that this is the size initialization, so there is no need to set the real size 121 sal_Bool bAllowToSetExtent = 122 ( ( getStatus( nAspect ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) 123 && !MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0x00020906L, 0x0000, 0x0000, 124 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 ) ) 125 && m_bHasCachedSize ); 126 127 if ( m_nObjectState == embed::EmbedStates::LOADED && bAllowToSetExtent ) 128 { 129 aGuard.clear(); 130 try { 131 changeState( embed::EmbedStates::RUNNING ); 132 } 133 catch( uno::Exception& ) 134 { 135 OSL_ENSURE( sal_False, "The object should not be resized without activation!\n" ); 136 } 137 aGuard.reset(); 138 } 139 140 if ( m_pOleComponent && m_nObjectState != embed::EmbedStates::LOADED && bAllowToSetExtent ) 141 { 142 awt::Size aSizeToSet = aSize; 143 aGuard.clear(); 144 try { 145 m_pOleComponent->SetExtent( aSizeToSet, nAspect ); // will throw an exception in case of failure 146 m_bHasSizeToSet = sal_False; 147 } 148 catch( uno::Exception& ) 149 { 150 // some objects do not allow to set the size even in running state 151 m_bHasSizeToSet = sal_True; 152 m_aSizeToSet = aSizeToSet; 153 m_nAspectToSet = nAspect; 154 } 155 aGuard.reset(); 156 } 157 #endif 158 159 // cache the values 160 m_bHasCachedSize = sal_True; 161 m_aCachedSize = aSize; 162 m_nCachedAspect = nAspect; 163 } 164 165 awt::Size SAL_CALL OleEmbeddedObject::getVisualAreaSize( sal_Int64 nAspect ) 166 throw ( lang::IllegalArgumentException, 167 embed::WrongStateException, 168 uno::Exception, 169 uno::RuntimeException ) 170 { 171 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::getVisualAreaSize" ); 172 173 // begin wrapping related part ==================== 174 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; 175 if ( xWrappedObject.is() ) 176 { 177 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 178 return xWrappedObject->getVisualAreaSize( nAspect ); 179 } 180 // end wrapping related part ==================== 181 182 ::osl::ResettableMutexGuard aGuard( m_aMutex ); 183 if ( m_bDisposed ) 184 throw lang::DisposedException(); // TODO 185 186 OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); 187 if ( nAspect == embed::Aspects::MSOLE_ICON ) 188 // no representation can be retrieved 189 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), 190 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 191 192 if ( m_nObjectState == -1 ) 193 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), 194 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 195 196 awt::Size aResult; 197 198 #ifdef WNT 199 // TODO/LATER: Support different aspects 200 if ( m_pOleComponent && !m_bHasSizeToSet && nAspect == embed::Aspects::MSOLE_CONTENT ) 201 { 202 try 203 { 204 // the cached size updated every time the object is stored 205 if ( m_bHasCachedSize ) 206 { 207 aResult = m_aCachedSize; 208 } 209 else 210 { 211 // there is no internal cache 212 awt::Size aSize; 213 aGuard.clear(); 214 215 sal_Bool bSuccess = sal_False; 216 if ( getCurrentState() == embed::EmbedStates::LOADED ) 217 { 218 OSL_ENSURE( sal_False, "Loaded object has no cached size!\n" ); 219 220 // try to switch the object to RUNNING state and request the value again 221 try { 222 changeState( embed::EmbedStates::RUNNING ); 223 } 224 catch( uno::Exception ) 225 { 226 throw embed::NoVisualAreaSizeException( 227 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), 228 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 229 } 230 } 231 232 try 233 { 234 // first try to get size using replacement image 235 aSize = m_pOleComponent->GetExtent( nAspect ); // will throw an exception in case of failure 236 bSuccess = sal_True; 237 } 238 catch( uno::Exception& ) 239 { 240 } 241 242 if ( !bSuccess ) 243 { 244 try 245 { 246 // second try the cached replacement image 247 aSize = m_pOleComponent->GetCachedExtent( nAspect ); // will throw an exception in case of failure 248 bSuccess = sal_True; 249 } 250 catch( uno::Exception& ) 251 { 252 } 253 } 254 255 if ( !bSuccess ) 256 { 257 try 258 { 259 // third try the size reported by the object 260 aSize = m_pOleComponent->GetReccomendedExtent( nAspect ); // will throw an exception in case of failure 261 bSuccess = sal_True; 262 } 263 catch( uno::Exception& ) 264 { 265 } 266 } 267 268 if ( !bSuccess ) 269 throw embed::NoVisualAreaSizeException( 270 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), 271 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 272 273 aGuard.reset(); 274 275 m_aCachedSize = aSize; 276 m_nCachedAspect = nAspect; 277 m_bHasCachedSize = sal_True; 278 279 aResult = m_aCachedSize; 280 } 281 } 282 catch ( embed::NoVisualAreaSizeException& ) 283 { 284 throw; 285 } 286 catch ( uno::Exception& ) 287 { 288 throw embed::NoVisualAreaSizeException( 289 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), 290 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 291 } 292 } 293 else 294 #endif 295 { 296 // return cached value 297 if ( m_bHasCachedSize ) 298 { 299 OSL_ENSURE( nAspect == m_nCachedAspect, "Unexpected aspect is requested!\n" ); 300 aResult = m_aCachedSize; 301 } 302 else 303 { 304 throw embed::NoVisualAreaSizeException( 305 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), 306 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 307 } 308 } 309 310 return aResult; 311 } 312 313 embed::VisualRepresentation SAL_CALL OleEmbeddedObject::getPreferredVisualRepresentation( sal_Int64 nAspect ) 314 throw ( lang::IllegalArgumentException, 315 embed::WrongStateException, 316 uno::Exception, 317 uno::RuntimeException ) 318 { 319 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::getPreferredVisualRepresentation" ); 320 321 // begin wrapping related part ==================== 322 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; 323 if ( xWrappedObject.is() ) 324 { 325 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 326 return xWrappedObject->getPreferredVisualRepresentation( nAspect ); 327 } 328 // end wrapping related part ==================== 329 330 ::osl::MutexGuard aGuard( m_aMutex ); 331 if ( m_bDisposed ) 332 throw lang::DisposedException(); // TODO 333 334 OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); 335 if ( nAspect == embed::Aspects::MSOLE_ICON ) 336 // no representation can be retrieved 337 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), 338 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 339 340 // TODO: if the object has cached representation then it should be returned 341 // TODO: if the object has no cached representation and is in loaded state it should switch itself to the running state 342 if ( m_nObjectState == -1 ) 343 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), 344 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 345 346 embed::VisualRepresentation aVisualRepr; 347 348 // TODO: in case of different aspects they must be applied to the mediatype and XTransferable must be used 349 // the cache is used only as a fallback if object is not in loaded state 350 if ( !m_xCachedVisualRepresentation.is() && ( !m_bVisReplInitialized || m_bVisReplInStream ) 351 && m_nObjectState == embed::EmbedStates::LOADED ) 352 { 353 m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream, sal_True ); 354 SetVisReplInStream( m_xCachedVisualRepresentation.is() ); 355 } 356 357 if ( m_xCachedVisualRepresentation.is() ) 358 { 359 return GetVisualRepresentationInNativeFormat_Impl( m_xCachedVisualRepresentation ); 360 } 361 #ifdef WNT 362 else if ( m_pOleComponent ) 363 { 364 try 365 { 366 if ( m_nObjectState == embed::EmbedStates::LOADED ) 367 changeState( embed::EmbedStates::RUNNING ); 368 369 datatransfer::DataFlavor aDataFlavor( 370 ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ), 371 ::rtl::OUString::createFromAscii( "Windows Metafile" ), 372 ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); 373 374 aVisualRepr.Data = m_pOleComponent->getTransferData( aDataFlavor ); 375 aVisualRepr.Flavor = aDataFlavor; 376 377 uno::Sequence< sal_Int8 > aVisReplSeq; 378 aVisualRepr.Data >>= aVisReplSeq; 379 if ( aVisReplSeq.getLength() ) 380 { 381 m_xCachedVisualRepresentation = GetNewFilledTempStream_Impl( 382 uno::Reference< io::XInputStream > ( static_cast< io::XInputStream* > ( 383 new ::comphelper::SequenceInputStream( aVisReplSeq ) ) ) ); 384 } 385 386 return aVisualRepr; 387 } 388 catch( uno::Exception& ) 389 {} 390 } 391 #endif 392 393 // the cache is used only as a fallback if object is not in loaded state 394 if ( !m_xCachedVisualRepresentation.is() && ( !m_bVisReplInitialized || m_bVisReplInStream ) ) 395 { 396 m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream ); 397 SetVisReplInStream( m_xCachedVisualRepresentation.is() ); 398 } 399 400 if ( !m_xCachedVisualRepresentation.is() ) 401 { 402 // no representation can be retrieved 403 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), 404 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 405 } 406 407 return GetVisualRepresentationInNativeFormat_Impl( m_xCachedVisualRepresentation ); 408 } 409 410 sal_Int32 SAL_CALL OleEmbeddedObject::getMapUnit( sal_Int64 nAspect ) 411 throw ( uno::Exception, 412 uno::RuntimeException) 413 { 414 // begin wrapping related part ==================== 415 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; 416 if ( xWrappedObject.is() ) 417 { 418 // the object was converted to OOo embedded object, the current implementation is now only a wrapper 419 return xWrappedObject->getMapUnit( nAspect ); 420 } 421 // end wrapping related part ==================== 422 423 ::osl::MutexGuard aGuard( m_aMutex ); 424 if ( m_bDisposed ) 425 throw lang::DisposedException(); // TODO 426 427 OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); 428 if ( nAspect == embed::Aspects::MSOLE_ICON ) 429 // no representation can be retrieved 430 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), 431 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 432 433 if ( m_nObjectState == -1 ) 434 throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), 435 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); 436 437 return embed::EmbedMapUnits::ONE_100TH_MM; 438 } 439 440 441