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 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
setVisualAreaSize(sal_Int64 nAspect,const awt::Size & aSize)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
getVisualAreaSize(sal_Int64 nAspect)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
getPreferredVisualRepresentation(sal_Int64 nAspect)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
getMapUnit(sal_Int64 nAspect)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