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
GetVisualRepresentationInNativeFormat_Impl(const uno::Reference<io::XStream> xCachedVisRepr)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
setVisualAreaSize(sal_Int64 nAspect,const awt::Size & aSize)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
getVisualAreaSize(sal_Int64 nAspect)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
getPreferredVisualRepresentation(sal_Int64 nAspect)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
getMapUnit(sal_Int64 nAspect)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