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