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