| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_embeddedobj.hxx" |
| #include <com/sun/star/lang/DisposedException.hpp> |
| #include <com/sun/star/embed/EmbedStates.hpp> |
| #include <com/sun/star/embed/EmbedMapUnits.hpp> |
| #include <com/sun/star/embed/EmbedMisc.hpp> |
| #include <com/sun/star/embed/Aspects.hpp> |
| #include <com/sun/star/io/XSeekable.hpp> |
| #include <com/sun/star/embed/NoVisualAreaSizeException.hpp> |
| |
| #include <rtl/logfile.hxx> |
| |
| #include <oleembobj.hxx> |
| #include <olecomponent.hxx> |
| #include <comphelper/mimeconfighelper.hxx> |
| #include <comphelper/seqstream.hxx> |
| |
| using namespace ::com::sun::star; |
| using namespace ::comphelper; |
| |
| embed::VisualRepresentation OleEmbeddedObject::GetVisualRepresentationInNativeFormat_Impl( |
| const uno::Reference< io::XStream > xCachedVisRepr ) |
| throw ( uno::Exception ) |
| { |
| embed::VisualRepresentation aVisualRepr; |
| |
| // TODO: detect the format in the future for now use workaround |
| uno::Reference< io::XInputStream > xInStream = xCachedVisRepr->getInputStream(); |
| uno::Reference< io::XSeekable > xSeekable( xCachedVisRepr, uno::UNO_QUERY ); |
| if ( !xInStream.is() || !xSeekable.is() ) |
| throw uno::RuntimeException(); |
| |
| uno::Sequence< sal_Int8 > aSeq( 2 ); |
| xInStream->readBytes( aSeq, 2 ); |
| xSeekable->seek( 0 ); |
| if ( aSeq.getLength() == 2 && aSeq[0] == 'B' && aSeq[1] == 'M' ) |
| { |
| // it's a bitmap |
| aVisualRepr.Flavor = datatransfer::DataFlavor( |
| ::rtl::OUString::createFromAscii( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" ), |
| ::rtl::OUString::createFromAscii( "Bitmap" ), |
| ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); |
| } |
| else |
| { |
| // it's a metafile |
| aVisualRepr.Flavor = datatransfer::DataFlavor( |
| ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ), |
| ::rtl::OUString::createFromAscii( "Windows Metafile" ), |
| ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); |
| } |
| |
| sal_Int32 nStreamLength = (sal_Int32)xSeekable->getLength(); |
| uno::Sequence< sal_Int8 > aRepresent( nStreamLength ); |
| xInStream->readBytes( aRepresent, nStreamLength ); |
| aVisualRepr.Data <<= aRepresent; |
| |
| return aVisualRepr; |
| } |
| |
| void SAL_CALL OleEmbeddedObject::setVisualAreaSize( sal_Int64 nAspect, const awt::Size& aSize ) |
| throw ( lang::IllegalArgumentException, |
| embed::WrongStateException, |
| uno::Exception, |
| uno::RuntimeException ) |
| { |
| RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::setVisualAreaSize" ); |
| |
| // begin wrapping related part ==================== |
| uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; |
| if ( xWrappedObject.is() ) |
| { |
| // the object was converted to OOo embedded object, the current implementation is now only a wrapper |
| xWrappedObject->setVisualAreaSize( nAspect, aSize ); |
| return; |
| } |
| // end wrapping related part ==================== |
| |
| ::osl::ResettableMutexGuard aGuard( m_aMutex ); |
| if ( m_bDisposed ) |
| throw lang::DisposedException(); // TODO |
| |
| OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); |
| if ( nAspect == embed::Aspects::MSOLE_ICON ) |
| // no representation can be retrieved |
| throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| |
| if ( m_nObjectState == -1 ) |
| throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| |
| #ifdef WNT |
| // RECOMPOSE_ON_RESIZE misc flag means that the object has to be switched to running state on resize. |
| // SetExtent() is called only for objects that require it, |
| // it should not be called for MSWord documents to workaround problem i49369 |
| // If cached size is not set, that means that this is the size initialization, so there is no need to set the real size |
| sal_Bool bAllowToSetExtent = |
| ( ( getStatus( nAspect ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) |
| && !MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0x00020906L, 0x0000, 0x0000, |
| 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 ) ) |
| && m_bHasCachedSize ); |
| |
| if ( m_nObjectState == embed::EmbedStates::LOADED && bAllowToSetExtent ) |
| { |
| aGuard.clear(); |
| try { |
| changeState( embed::EmbedStates::RUNNING ); |
| } |
| catch( uno::Exception& ) |
| { |
| OSL_ENSURE( sal_False, "The object should not be resized without activation!\n" ); |
| } |
| aGuard.reset(); |
| } |
| |
| if ( m_pOleComponent && m_nObjectState != embed::EmbedStates::LOADED && bAllowToSetExtent ) |
| { |
| awt::Size aSizeToSet = aSize; |
| aGuard.clear(); |
| try { |
| m_pOleComponent->SetExtent( aSizeToSet, nAspect ); // will throw an exception in case of failure |
| m_bHasSizeToSet = sal_False; |
| } |
| catch( uno::Exception& ) |
| { |
| // some objects do not allow to set the size even in running state |
| m_bHasSizeToSet = sal_True; |
| m_aSizeToSet = aSizeToSet; |
| m_nAspectToSet = nAspect; |
| } |
| aGuard.reset(); |
| } |
| #endif |
| |
| // cache the values |
| m_bHasCachedSize = sal_True; |
| m_aCachedSize = aSize; |
| m_nCachedAspect = nAspect; |
| } |
| |
| awt::Size SAL_CALL OleEmbeddedObject::getVisualAreaSize( sal_Int64 nAspect ) |
| throw ( lang::IllegalArgumentException, |
| embed::WrongStateException, |
| uno::Exception, |
| uno::RuntimeException ) |
| { |
| RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::getVisualAreaSize" ); |
| |
| // begin wrapping related part ==================== |
| uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; |
| if ( xWrappedObject.is() ) |
| { |
| // the object was converted to OOo embedded object, the current implementation is now only a wrapper |
| return xWrappedObject->getVisualAreaSize( nAspect ); |
| } |
| // end wrapping related part ==================== |
| |
| ::osl::ResettableMutexGuard aGuard( m_aMutex ); |
| if ( m_bDisposed ) |
| throw lang::DisposedException(); // TODO |
| |
| OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); |
| if ( nAspect == embed::Aspects::MSOLE_ICON ) |
| // no representation can be retrieved |
| throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| |
| if ( m_nObjectState == -1 ) |
| throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| |
| awt::Size aResult; |
| |
| #ifdef WNT |
| // TODO/LATER: Support different aspects |
| if ( m_pOleComponent && !m_bHasSizeToSet && nAspect == embed::Aspects::MSOLE_CONTENT ) |
| { |
| try |
| { |
| // the cached size updated every time the object is stored |
| if ( m_bHasCachedSize ) |
| { |
| aResult = m_aCachedSize; |
| } |
| else |
| { |
| // there is no internal cache |
| awt::Size aSize; |
| aGuard.clear(); |
| |
| sal_Bool bSuccess = sal_False; |
| if ( getCurrentState() == embed::EmbedStates::LOADED ) |
| { |
| OSL_ENSURE( sal_False, "Loaded object has no cached size!\n" ); |
| |
| // try to switch the object to RUNNING state and request the value again |
| try { |
| changeState( embed::EmbedStates::RUNNING ); |
| } |
| catch( uno::Exception ) |
| { |
| throw embed::NoVisualAreaSizeException( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| } |
| } |
| |
| try |
| { |
| // first try to get size using replacement image |
| aSize = m_pOleComponent->GetExtent( nAspect ); // will throw an exception in case of failure |
| bSuccess = sal_True; |
| } |
| catch( uno::Exception& ) |
| { |
| } |
| |
| if ( !bSuccess ) |
| { |
| try |
| { |
| // second try the cached replacement image |
| aSize = m_pOleComponent->GetCachedExtent( nAspect ); // will throw an exception in case of failure |
| bSuccess = sal_True; |
| } |
| catch( uno::Exception& ) |
| { |
| } |
| } |
| |
| if ( !bSuccess ) |
| { |
| try |
| { |
| // third try the size reported by the object |
| aSize = m_pOleComponent->GetReccomendedExtent( nAspect ); // will throw an exception in case of failure |
| bSuccess = sal_True; |
| } |
| catch( uno::Exception& ) |
| { |
| } |
| } |
| |
| if ( !bSuccess ) |
| throw embed::NoVisualAreaSizeException( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| |
| aGuard.reset(); |
| |
| m_aCachedSize = aSize; |
| m_nCachedAspect = nAspect; |
| m_bHasCachedSize = sal_True; |
| |
| aResult = m_aCachedSize; |
| } |
| } |
| catch ( embed::NoVisualAreaSizeException& ) |
| { |
| throw; |
| } |
| catch ( uno::Exception& ) |
| { |
| throw embed::NoVisualAreaSizeException( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| } |
| } |
| else |
| #endif |
| { |
| // return cached value |
| if ( m_bHasCachedSize ) |
| { |
| OSL_ENSURE( nAspect == m_nCachedAspect, "Unexpected aspect is requested!\n" ); |
| aResult = m_aCachedSize; |
| } |
| else |
| { |
| throw embed::NoVisualAreaSizeException( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| } |
| } |
| |
| return aResult; |
| } |
| |
| embed::VisualRepresentation SAL_CALL OleEmbeddedObject::getPreferredVisualRepresentation( sal_Int64 nAspect ) |
| throw ( lang::IllegalArgumentException, |
| embed::WrongStateException, |
| uno::Exception, |
| uno::RuntimeException ) |
| { |
| RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::getPreferredVisualRepresentation" ); |
| |
| // begin wrapping related part ==================== |
| uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; |
| if ( xWrappedObject.is() ) |
| { |
| // the object was converted to OOo embedded object, the current implementation is now only a wrapper |
| return xWrappedObject->getPreferredVisualRepresentation( nAspect ); |
| } |
| // end wrapping related part ==================== |
| |
| ::osl::MutexGuard aGuard( m_aMutex ); |
| if ( m_bDisposed ) |
| throw lang::DisposedException(); // TODO |
| |
| OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); |
| if ( nAspect == embed::Aspects::MSOLE_ICON ) |
| // no representation can be retrieved |
| throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| |
| // TODO: if the object has cached representation then it should be returned |
| // TODO: if the object has no cached representation and is in loaded state it should switch itself to the running state |
| if ( m_nObjectState == -1 ) |
| throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| |
| embed::VisualRepresentation aVisualRepr; |
| |
| // TODO: in case of different aspects they must be applied to the mediatype and XTransferable must be used |
| // the cache is used only as a fallback if object is not in loaded state |
| if ( !m_xCachedVisualRepresentation.is() && ( !m_bVisReplInitialized || m_bVisReplInStream ) |
| && m_nObjectState == embed::EmbedStates::LOADED ) |
| { |
| m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream, sal_True ); |
| SetVisReplInStream( m_xCachedVisualRepresentation.is() ); |
| } |
| |
| if ( m_xCachedVisualRepresentation.is() ) |
| { |
| return GetVisualRepresentationInNativeFormat_Impl( m_xCachedVisualRepresentation ); |
| } |
| #ifdef WNT |
| else if ( m_pOleComponent ) |
| { |
| try |
| { |
| if ( m_nObjectState == embed::EmbedStates::LOADED ) |
| changeState( embed::EmbedStates::RUNNING ); |
| |
| datatransfer::DataFlavor aDataFlavor( |
| ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ), |
| ::rtl::OUString::createFromAscii( "Windows Metafile" ), |
| ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); |
| |
| aVisualRepr.Data = m_pOleComponent->getTransferData( aDataFlavor ); |
| aVisualRepr.Flavor = aDataFlavor; |
| |
| uno::Sequence< sal_Int8 > aVisReplSeq; |
| aVisualRepr.Data >>= aVisReplSeq; |
| if ( aVisReplSeq.getLength() ) |
| { |
| m_xCachedVisualRepresentation = GetNewFilledTempStream_Impl( |
| uno::Reference< io::XInputStream > ( static_cast< io::XInputStream* > ( |
| new ::comphelper::SequenceInputStream( aVisReplSeq ) ) ) ); |
| } |
| |
| return aVisualRepr; |
| } |
| catch( uno::Exception& ) |
| {} |
| } |
| #endif |
| |
| // the cache is used only as a fallback if object is not in loaded state |
| if ( !m_xCachedVisualRepresentation.is() && ( !m_bVisReplInitialized || m_bVisReplInStream ) ) |
| { |
| m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream ); |
| SetVisReplInStream( m_xCachedVisualRepresentation.is() ); |
| } |
| |
| if ( !m_xCachedVisualRepresentation.is() ) |
| { |
| // no representation can be retrieved |
| throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| } |
| |
| return GetVisualRepresentationInNativeFormat_Impl( m_xCachedVisualRepresentation ); |
| } |
| |
| sal_Int32 SAL_CALL OleEmbeddedObject::getMapUnit( sal_Int64 nAspect ) |
| throw ( uno::Exception, |
| uno::RuntimeException) |
| { |
| // begin wrapping related part ==================== |
| uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; |
| if ( xWrappedObject.is() ) |
| { |
| // the object was converted to OOo embedded object, the current implementation is now only a wrapper |
| return xWrappedObject->getMapUnit( nAspect ); |
| } |
| // end wrapping related part ==================== |
| |
| ::osl::MutexGuard aGuard( m_aMutex ); |
| if ( m_bDisposed ) |
| throw lang::DisposedException(); // TODO |
| |
| OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); |
| if ( nAspect == embed::Aspects::MSOLE_ICON ) |
| // no representation can be retrieved |
| throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| |
| if ( m_nObjectState == -1 ) |
| throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), |
| uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); |
| |
| return embed::EmbedMapUnits::ONE_100TH_MM; |
| } |
| |
| |