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