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