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 <osl/mutex.hxx>
21 : #include <vcl/svapp.hxx>
22 : #include <vcl/image.hxx>
23 : #include <vcl/metaact.hxx>
24 : #include <vcl/msgbox.hxx>
25 : #include <vcl/imagerepository.hxx>
26 : #include <tools/rcid.h>
27 : #include <tools/resid.hxx>
28 : #include <tools/resmgr.hxx>
29 : #include <unotools/ucbstreamhelper.hxx>
30 : #include <vcl/graphicfilter.hxx>
31 : #include <vcl/wmf.hxx>
32 : #include <svl/solar.hrc>
33 : #include <vcl/virdev.hxx>
34 : #include <vcl/settings.hxx>
35 : #include <com/sun/star/io/XStream.hpp>
36 : #include <com/sun/star/text/GraphicCrop.hpp>
37 : #include <com/sun/star/uno/XComponentContext.hpp>
38 : #include <comphelper/servicehelper.hxx>
39 : #include <cppuhelper/supportsservice.hxx>
40 :
41 : #include "descriptor.hxx"
42 : #include "graphic.hxx"
43 : #include <rtl/ref.hxx>
44 : #include <svtools/grfmgr.hxx>
45 : #include "provider.hxx"
46 : #include <vcl/dibtools.hxx>
47 : #include <boost/scoped_ptr.hpp>
48 :
49 : using namespace com::sun::star;
50 :
51 : namespace {
52 :
53 : #define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:"
54 :
55 145945 : GraphicProvider::GraphicProvider()
56 : {
57 145945 : }
58 :
59 291886 : GraphicProvider::~GraphicProvider()
60 : {
61 291886 : }
62 :
63 0 : OUString SAL_CALL GraphicProvider::getImplementationName()
64 : throw( uno::RuntimeException, std::exception )
65 : {
66 0 : return OUString( "com.sun.star.comp.graphic.GraphicProvider" );
67 : }
68 :
69 0 : sal_Bool SAL_CALL GraphicProvider::supportsService( const OUString& ServiceName )
70 : throw( uno::RuntimeException, std::exception )
71 : {
72 0 : return cppu::supportsService( this, ServiceName );
73 : }
74 :
75 0 : uno::Sequence< OUString > SAL_CALL GraphicProvider::getSupportedServiceNames()
76 : throw( uno::RuntimeException, std::exception )
77 : {
78 0 : uno::Sequence< OUString > aSeq( 1 );
79 0 : aSeq.getArray()[ 0 ] = "com.sun.star.graphic.GraphicProvider";
80 0 : return aSeq;
81 : }
82 :
83 0 : uno::Sequence< uno::Type > SAL_CALL GraphicProvider::getTypes()
84 : throw(uno::RuntimeException, std::exception)
85 : {
86 0 : uno::Sequence< uno::Type > aTypes( 3 );
87 0 : uno::Type* pTypes = aTypes.getArray();
88 :
89 0 : *pTypes++ = cppu::UnoType<lang::XServiceInfo>::get();
90 0 : *pTypes++ = cppu::UnoType<lang::XTypeProvider>::get();
91 0 : *pTypes++ = cppu::UnoType<graphic::XGraphicProvider>::get();
92 :
93 0 : return aTypes;
94 : }
95 :
96 0 : uno::Sequence< sal_Int8 > SAL_CALL GraphicProvider::getImplementationId()
97 : throw(uno::RuntimeException, std::exception)
98 : {
99 0 : return css::uno::Sequence<sal_Int8>();
100 : }
101 :
102 :
103 :
104 5871 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadGraphicObject( const OUString& rResourceURL ) const
105 : {
106 5871 : uno::Reference< ::graphic::XGraphic > xRet;
107 5871 : if( rResourceURL.startsWith( UNO_NAME_GRAPHOBJ_URLPREFIX ) )
108 : {
109 : // graphic manager url
110 448 : OUString aTmpStr( rResourceURL.copy( sizeof( UNO_NAME_GRAPHOBJ_URLPREFIX ) - 1 ) );
111 : OString aUniqueID(OUStringToOString(aTmpStr,
112 896 : RTL_TEXTENCODING_UTF8));
113 896 : GraphicObject aGrafObj(aUniqueID);
114 : // I don't call aGrafObj.GetXGraphic because it will call us back
115 : // into implLoadMemory ( with "private:memorygraphic" test )
116 448 : ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
117 448 : pUnoGraphic->init( aGrafObj.GetGraphic() );
118 896 : xRet = pUnoGraphic;
119 : }
120 5871 : return xRet;
121 : }
122 :
123 141949 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadMemory( const OUString& rResourceURL ) const
124 : {
125 141949 : uno::Reference< ::graphic::XGraphic > xRet;
126 141949 : sal_Int32 nIndex = 0;
127 :
128 141949 : if( rResourceURL.getToken( 0, '/', nIndex ).equalsAscii( "private:memorygraphic" ) )
129 : {
130 136078 : sal_Int64 nGraphicAddress = rResourceURL.getToken( 0, '/', nIndex ).toInt64();
131 :
132 136078 : if( nGraphicAddress )
133 : {
134 136078 : ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
135 :
136 136078 : pUnoGraphic->init( *reinterpret_cast< ::Graphic* >( nGraphicAddress ) );
137 136078 : xRet = pUnoGraphic;
138 : }
139 : }
140 :
141 141949 : return xRet;
142 : }
143 :
144 :
145 :
146 5423 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadRepositoryImage( const OUString& rResourceURL ) const
147 : {
148 5423 : uno::Reference< ::graphic::XGraphic > xRet;
149 5423 : sal_Int32 nIndex = 0;
150 :
151 5423 : if( rResourceURL.getToken( 0, '/', nIndex ).equalsAscii( "private:graphicrepository" ) )
152 : {
153 5364 : OUString sPathName( rResourceURL.copy( nIndex ) );
154 10728 : BitmapEx aBitmap;
155 5364 : if ( ::vcl::ImageRepository::loadImage( sPathName, aBitmap, false ) )
156 : {
157 5364 : Image aImage( aBitmap );
158 5364 : xRet = aImage.GetXGraphic();
159 5364 : }
160 : }
161 5423 : return xRet;
162 : }
163 :
164 :
165 :
166 :
167 59 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadStandardImage( const OUString& rResourceURL ) const
168 : {
169 59 : uno::Reference< ::graphic::XGraphic > xRet;
170 59 : sal_Int32 nIndex = 0;
171 :
172 59 : if( rResourceURL.getToken( 0, '/', nIndex ).equalsAscii( "private:standardimage" ) )
173 : {
174 0 : OUString sImageName( rResourceURL.copy( nIndex ) );
175 0 : if ( sImageName == "info" )
176 : {
177 0 : xRet = InfoBox::GetStandardImage().GetXGraphic();
178 : }
179 0 : else if ( sImageName == "warning" )
180 : {
181 0 : xRet = WarningBox::GetStandardImage().GetXGraphic();
182 : }
183 0 : else if ( sImageName == "error" )
184 : {
185 0 : xRet = ErrorBox::GetStandardImage().GetXGraphic();
186 : }
187 0 : else if ( sImageName == "query" )
188 : {
189 0 : xRet = QueryBox::GetStandardImage().GetXGraphic();
190 0 : }
191 : }
192 59 : return xRet;
193 : }
194 :
195 :
196 :
197 0 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadBitmap( const uno::Reference< awt::XBitmap >& xBtm ) const
198 : {
199 0 : uno::Reference< ::graphic::XGraphic > xRet;
200 0 : uno::Sequence< sal_Int8 > aBmpSeq( xBtm->getDIB() );
201 0 : uno::Sequence< sal_Int8 > aMaskSeq( xBtm->getMaskDIB() );
202 0 : SvMemoryStream aBmpStream( aBmpSeq.getArray(), aBmpSeq.getLength(), STREAM_READ );
203 0 : Bitmap aBmp;
204 0 : BitmapEx aBmpEx;
205 :
206 0 : ReadDIB(aBmp, aBmpStream, true);
207 :
208 0 : if( aMaskSeq.getLength() )
209 : {
210 0 : SvMemoryStream aMaskStream( aMaskSeq.getArray(), aMaskSeq.getLength(), STREAM_READ );
211 0 : Bitmap aMask;
212 :
213 0 : ReadDIB(aMask, aMaskStream, true);
214 0 : aBmpEx = BitmapEx( aBmp, aMask );
215 : }
216 : else
217 0 : aBmpEx = BitmapEx( aBmp );
218 :
219 0 : if( !aBmpEx.IsEmpty() )
220 : {
221 0 : ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
222 :
223 0 : pUnoGraphic->init( aBmpEx );
224 0 : xRet = pUnoGraphic;
225 : }
226 0 : return xRet;
227 : }
228 :
229 :
230 :
231 5423 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadResource( const OUString& rResourceURL ) const
232 : {
233 5423 : uno::Reference< ::graphic::XGraphic > xRet;
234 5423 : sal_Int32 nIndex = 0;
235 :
236 5423 : if( rResourceURL.getToken( 0, '/', nIndex ).equalsAscii( "private:resource" ) )
237 : {
238 : OString aResMgrName(OUStringToOString(
239 0 : rResourceURL.getToken(0, '/', nIndex), RTL_TEXTENCODING_ASCII_US));
240 :
241 0 : boost::scoped_ptr<ResMgr> pResMgr(ResMgr::CreateResMgr( aResMgrName.getStr(), Application::GetSettings().GetUILanguageTag() ));
242 :
243 0 : if( pResMgr )
244 : {
245 0 : const OUString aResourceType( rResourceURL.getToken( 0, '/', nIndex ) );
246 0 : const ResId aResId( rResourceURL.getToken( 0, '/', nIndex ).toInt32(), *pResMgr );
247 :
248 0 : if( !aResourceType.isEmpty() )
249 : {
250 0 : BitmapEx aBmpEx;
251 :
252 0 : if( aResourceType.equalsAscii( "bitmap" ) ||
253 0 : aResourceType.equalsAscii( "bitmapex" ) )
254 : {
255 0 : aResId.SetRT( RSC_BITMAP );
256 :
257 0 : if( pResMgr->IsAvailable( aResId ) )
258 : {
259 0 : aBmpEx = BitmapEx( aResId );
260 : }
261 : }
262 0 : else if( aResourceType.equalsAscii( "image" ) )
263 : {
264 0 : aResId.SetRT( RSC_IMAGE );
265 :
266 0 : if( pResMgr->IsAvailable( aResId ) )
267 : {
268 0 : const Image aImage( aResId );
269 0 : aBmpEx = aImage.GetBitmapEx();
270 : }
271 : }
272 0 : else if( aResourceType.equalsAscii( "imagelist" ) )
273 : {
274 0 : aResId.SetRT( RSC_IMAGELIST );
275 :
276 0 : if( pResMgr->IsAvailable( aResId ) )
277 : {
278 0 : const ImageList aImageList( aResId );
279 0 : sal_Int32 nImageId = ( nIndex > -1 ) ? rResourceURL.getToken( 0, '/', nIndex ).toInt32() : 0;
280 :
281 0 : if( 0 < nImageId )
282 : {
283 0 : const Image aImage( aImageList.GetImage( sal::static_int_cast< sal_uInt16 >(nImageId) ) );
284 0 : aBmpEx = aImage.GetBitmapEx();
285 : }
286 : else
287 : {
288 0 : aBmpEx = aImageList.GetAsHorizontalStrip();
289 0 : }
290 : }
291 : }
292 :
293 0 : if( !aBmpEx.IsEmpty() )
294 : {
295 0 : ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
296 :
297 0 : pUnoGraphic->init( aBmpEx );
298 0 : xRet = pUnoGraphic;
299 0 : }
300 0 : }
301 0 : }
302 : }
303 :
304 5423 : return xRet;
305 : }
306 :
307 :
308 :
309 0 : uno::Reference< beans::XPropertySet > SAL_CALL GraphicProvider::queryGraphicDescriptor( const uno::Sequence< beans::PropertyValue >& rMediaProperties )
310 : throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
311 : {
312 0 : uno::Reference< beans::XPropertySet > xRet;
313 :
314 0 : OUString aURL;
315 0 : uno::Reference< io::XInputStream > xIStm;
316 0 : uno::Reference< awt::XBitmap >xBtm;
317 :
318 0 : for( sal_Int32 i = 0; ( i < rMediaProperties.getLength() ) && !xRet.is(); ++i )
319 : {
320 0 : const OUString aName( rMediaProperties[ i ].Name );
321 0 : const uno::Any aValue( rMediaProperties[ i ].Value );
322 :
323 0 : if (aName == "URL")
324 : {
325 0 : aValue >>= aURL;
326 : }
327 0 : else if (aName == "InputStream")
328 : {
329 0 : aValue >>= xIStm;
330 : }
331 0 : else if (aName == "Bitmap")
332 : {
333 0 : aValue >>= xBtm;
334 : }
335 0 : }
336 :
337 0 : SolarMutexGuard g;
338 :
339 0 : if( xIStm.is() )
340 : {
341 0 : unographic::GraphicDescriptor* pDescriptor = new unographic::GraphicDescriptor;
342 0 : pDescriptor->init( xIStm, aURL );
343 0 : xRet = pDescriptor;
344 : }
345 0 : else if( !aURL.isEmpty() )
346 : {
347 0 : uno::Reference< ::graphic::XGraphic > xGraphic( implLoadMemory( aURL ) );
348 0 : if( !xGraphic.is() )
349 0 : xGraphic = implLoadResource( aURL );
350 0 : if( !xGraphic.is() )
351 0 : xGraphic = implLoadGraphicObject( aURL );
352 :
353 0 : if ( !xGraphic.is() )
354 0 : xGraphic = implLoadRepositoryImage( aURL );
355 :
356 0 : if ( !xGraphic.is() )
357 0 : xGraphic = implLoadStandardImage( aURL );
358 :
359 0 : if( xGraphic.is() )
360 : {
361 0 : xRet = uno::Reference< beans::XPropertySet >( xGraphic, uno::UNO_QUERY );
362 : }
363 : else
364 : {
365 0 : unographic::GraphicDescriptor* pDescriptor = new unographic::GraphicDescriptor;
366 0 : pDescriptor->init( aURL );
367 0 : xRet = pDescriptor;
368 0 : }
369 : }
370 0 : else if( xBtm.is() )
371 : {
372 0 : uno::Reference< ::graphic::XGraphic > xGraphic( implLoadBitmap( xBtm ) );
373 0 : if( xGraphic.is() )
374 0 : xRet = uno::Reference< beans::XPropertySet >( xGraphic, uno::UNO_QUERY );
375 : }
376 :
377 0 : return xRet;
378 : }
379 :
380 :
381 :
382 143049 : uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( const uno::Sequence< ::beans::PropertyValue >& rMediaProperties )
383 : throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
384 : {
385 143049 : uno::Reference< ::graphic::XGraphic > xRet;
386 286098 : OUString aPath;
387 286098 : boost::scoped_ptr<SvStream> pIStm;
388 :
389 286098 : uno::Reference< io::XInputStream > xIStm;
390 286098 : uno::Reference< awt::XBitmap >xBtm;
391 :
392 286098 : uno::Sequence< ::beans::PropertyValue > aFilterData;
393 :
394 286112 : for( sal_Int32 i = 0; ( i < rMediaProperties.getLength() ) && !pIStm && !xRet.is(); ++i )
395 : {
396 143063 : const OUString aName( rMediaProperties[ i ].Name );
397 286126 : const uno::Any aValue( rMediaProperties[ i ].Value );
398 :
399 143063 : if (aName == "URL")
400 : {
401 142121 : OUString aURL;
402 142121 : aValue >>= aURL;
403 142121 : aPath = aURL;
404 : }
405 942 : else if (aName == "InputStream")
406 : {
407 928 : aValue >>= xIStm;
408 : }
409 14 : else if (aName == "Bitmap")
410 : {
411 0 : aValue >>= xBtm;
412 : }
413 14 : else if (aName == "FilterData")
414 : {
415 14 : aValue >>= aFilterData;
416 : }
417 143063 : }
418 :
419 : // Check for the goal width and height if they are defined
420 143049 : sal_uInt16 nExtWidth = 0;
421 143049 : sal_uInt16 nExtHeight = 0;
422 143049 : sal_uInt16 nExtMapMode = 0;
423 143091 : for( sal_Int32 i = 0; i < aFilterData.getLength(); ++i )
424 : {
425 42 : const OUString aName( aFilterData[ i ].Name );
426 84 : const uno::Any aValue( aFilterData[ i ].Value );
427 :
428 42 : if (aName == "ExternalWidth")
429 : {
430 14 : aValue >>= nExtWidth;
431 : }
432 28 : else if (aName == "ExternalHeight")
433 : {
434 14 : aValue >>= nExtHeight;
435 : }
436 14 : else if (aName == "ExternalMapMode")
437 : {
438 14 : aValue >>= nExtMapMode;
439 : }
440 42 : }
441 :
442 286098 : SolarMutexGuard g;
443 :
444 143049 : if( xIStm.is() )
445 : {
446 928 : pIStm.reset(::utl::UcbStreamHelper::CreateStream( xIStm ));
447 : }
448 142121 : else if( !aPath.isEmpty() )
449 : {
450 141949 : xRet = implLoadMemory( aPath );
451 :
452 141949 : if( !xRet.is() )
453 5871 : xRet = implLoadGraphicObject( aPath );
454 :
455 141949 : if( !xRet.is() )
456 5423 : xRet = implLoadResource( aPath );
457 :
458 141949 : if ( !xRet.is() )
459 5423 : xRet = implLoadRepositoryImage( aPath );
460 :
461 141949 : if ( !xRet.is() )
462 59 : xRet = implLoadStandardImage( aPath );
463 :
464 141949 : if( !xRet.is() )
465 59 : pIStm.reset(::utl::UcbStreamHelper::CreateStream( aPath, STREAM_READ ));
466 : }
467 172 : else if( xBtm.is() )
468 : {
469 0 : xRet = implLoadBitmap( xBtm );
470 : }
471 :
472 143049 : if( pIStm )
473 : {
474 987 : ::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter();
475 :
476 : {
477 987 : ::Graphic aVCLGraphic;
478 :
479 : // Define APM Header if goal height and width are defined
480 987 : WMF_EXTERNALHEADER aExtHeader;
481 987 : aExtHeader.xExt = nExtWidth;
482 987 : aExtHeader.yExt = nExtHeight;
483 987 : aExtHeader.mapMode = nExtMapMode;
484 987 : WMF_EXTERNALHEADER *pExtHeader = NULL;
485 987 : if ( nExtMapMode > 0 )
486 14 : pExtHeader = &aExtHeader;
487 :
488 1974 : if( ( rFilter.ImportGraphic( aVCLGraphic, aPath, *pIStm,
489 1913 : GRFILTER_FORMAT_DONTKNOW, NULL, 0, pExtHeader ) == GRFILTER_OK ) &&
490 926 : ( aVCLGraphic.GetType() != GRAPHIC_NONE ) )
491 : {
492 926 : ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
493 :
494 926 : pUnoGraphic->init( aVCLGraphic );
495 926 : xRet = pUnoGraphic;
496 987 : }
497 : }
498 : }
499 :
500 286098 : return xRet;
501 : }
502 :
503 2 : void ImplCalculateCropRect( ::Graphic& rGraphic, const text::GraphicCrop& rGraphicCropLogic, Rectangle& rGraphicCropPixel )
504 : {
505 2 : if ( rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom )
506 : {
507 0 : Size aSourceSizePixel( rGraphic.GetSizePixel() );
508 0 : if ( aSourceSizePixel.Width() && aSourceSizePixel.Height() )
509 : {
510 0 : if ( rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom )
511 : {
512 0 : Size aSize100thMM( 0, 0 );
513 0 : if( rGraphic.GetPrefMapMode().GetMapUnit() != MAP_PIXEL )
514 : {
515 0 : aSize100thMM = OutputDevice::LogicToLogic( rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), MAP_100TH_MM );
516 : }
517 : else
518 : {
519 0 : aSize100thMM = Application::GetDefaultDevice()->PixelToLogic( rGraphic.GetPrefSize(), MAP_100TH_MM );
520 : }
521 0 : if ( aSize100thMM.Width() && aSize100thMM.Height() )
522 : {
523 0 : double fSourceSizePixelWidth = static_cast<double>(aSourceSizePixel.Width());
524 0 : double fSourceSizePixelHeight= static_cast<double>(aSourceSizePixel.Height());
525 0 : rGraphicCropPixel.Left() = static_cast< sal_Int32 >((fSourceSizePixelWidth * rGraphicCropLogic.Left ) / aSize100thMM.Width());
526 0 : rGraphicCropPixel.Top() = static_cast< sal_Int32 >((fSourceSizePixelHeight * rGraphicCropLogic.Top ) / aSize100thMM.Height());
527 0 : rGraphicCropPixel.Right() = static_cast< sal_Int32 >(( fSourceSizePixelWidth * ( aSize100thMM.Width() - rGraphicCropLogic.Right ) ) / aSize100thMM.Width() );
528 0 : rGraphicCropPixel.Bottom() = static_cast< sal_Int32 >(( fSourceSizePixelHeight * ( aSize100thMM.Height() - rGraphicCropLogic.Bottom ) ) / aSize100thMM.Height() );
529 : }
530 : }
531 : }
532 : }
533 2 : }
534 :
535 2 : void ImplApplyBitmapScaling( ::Graphic& rGraphic, sal_Int32 nPixelWidth, sal_Int32 nPixelHeight )
536 : {
537 2 : if ( nPixelWidth && nPixelHeight )
538 : {
539 0 : BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
540 0 : MapMode aPrefMapMode( aBmpEx.GetPrefMapMode() );
541 0 : Size aPrefSize( aBmpEx.GetPrefSize() );
542 0 : aBmpEx.Scale( Size( nPixelWidth, nPixelHeight ) );
543 0 : aBmpEx.SetPrefMapMode( aPrefMapMode );
544 0 : aBmpEx.SetPrefSize( aPrefSize );
545 0 : rGraphic = aBmpEx;
546 : }
547 2 : }
548 :
549 2 : void ImplApplyBitmapResolution( ::Graphic& rGraphic, sal_Int32 nImageResolution, const Size& rVisiblePixelSize, const awt::Size& rLogicalSize )
550 : {
551 2 : if ( nImageResolution && rLogicalSize.Width && rLogicalSize.Height )
552 : {
553 0 : const double fImageResolution = static_cast<double>( nImageResolution );
554 0 : const double fSourceDPIX = ( static_cast<double>(rVisiblePixelSize.Width()) * 2540.0 ) / static_cast<double>(rLogicalSize.Width);
555 0 : const double fSourceDPIY = ( static_cast<double>(rVisiblePixelSize.Height()) * 2540.0 ) / static_cast<double>(rLogicalSize.Height);
556 0 : const sal_Int32 nSourcePixelWidth( rGraphic.GetSizePixel().Width() );
557 0 : const sal_Int32 nSourcePixelHeight( rGraphic.GetSizePixel().Height() );
558 0 : const double fSourcePixelWidth = static_cast<double>( nSourcePixelWidth );
559 0 : const double fSourcePixelHeight= static_cast<double>( nSourcePixelHeight );
560 :
561 0 : sal_Int32 nDestPixelWidth = nSourcePixelWidth;
562 0 : sal_Int32 nDestPixelHeight = nSourcePixelHeight;
563 :
564 : // check, if the bitmap DPI exceeds the maximum DPI
565 0 : if( fSourceDPIX > fImageResolution )
566 : {
567 0 : nDestPixelWidth = static_cast<sal_Int32>(( fSourcePixelWidth * fImageResolution ) / fSourceDPIX);
568 0 : if ( !nDestPixelWidth || ( nDestPixelWidth > nSourcePixelWidth ) )
569 0 : nDestPixelWidth = nSourcePixelWidth;
570 : }
571 0 : if ( fSourceDPIY > fImageResolution )
572 : {
573 0 : nDestPixelHeight= static_cast<sal_Int32>(( fSourcePixelHeight* fImageResolution ) / fSourceDPIY);
574 0 : if ( !nDestPixelHeight || ( nDestPixelHeight > nSourcePixelHeight ) )
575 0 : nDestPixelHeight = nSourcePixelHeight;
576 : }
577 0 : if ( ( nDestPixelWidth != nSourcePixelWidth ) || ( nDestPixelHeight != nSourcePixelHeight ) )
578 0 : ImplApplyBitmapScaling( rGraphic, nDestPixelWidth, nDestPixelHeight );
579 : }
580 2 : }
581 :
582 2 : void ImplApplyFilterData( ::Graphic& rGraphic, uno::Sequence< beans::PropertyValue >& rFilterData )
583 : {
584 : /* this method applies following attributes to the graphic, in the first step the
585 : cropping area (logical size in 100thmm) is applied, in the second step the resolution
586 : is applied, in the third step the graphic is scaled to the corresponding pixelsize.
587 : if a parameter value is zero or not available the corresponding step will be skipped */
588 :
589 2 : sal_Int32 nPixelWidth = 0;
590 2 : sal_Int32 nPixelHeight= 0;
591 2 : sal_Int32 nImageResolution = 0;
592 2 : awt::Size aLogicalSize( 0, 0 );
593 2 : text::GraphicCrop aCropLogic( 0, 0, 0, 0 );
594 2 : bool bRemoveCropArea = true;
595 :
596 2 : for( sal_Int32 i = 0; i < rFilterData.getLength(); ++i )
597 : {
598 0 : const OUString aName( rFilterData[ i ].Name );
599 0 : const uno::Any aValue( rFilterData[ i ].Value );
600 :
601 0 : if (aName == "PixelWidth")
602 0 : aValue >>= nPixelWidth;
603 0 : else if (aName == "PixelHeight")
604 0 : aValue >>= nPixelHeight;
605 0 : else if (aName == "LogicalSize")
606 0 : aValue >>= aLogicalSize;
607 0 : else if (aName == "GraphicCropLogic")
608 0 : aValue >>= aCropLogic;
609 0 : else if (aName == "RemoveCropArea")
610 0 : aValue >>= bRemoveCropArea;
611 0 : else if (aName == "ImageResolution")
612 0 : aValue >>= nImageResolution;
613 0 : }
614 2 : if ( rGraphic.GetType() == GRAPHIC_BITMAP )
615 : {
616 2 : if(rGraphic.getSvgData().get())
617 : {
618 : // embedded Svg, no need to scale. Also no method to apply crop data currently
619 : }
620 : else
621 : {
622 2 : Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() );
623 2 : ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel );
624 2 : if ( bRemoveCropArea )
625 : {
626 2 : BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
627 2 : aBmpEx.Crop( aCropPixel );
628 2 : rGraphic = aBmpEx;
629 : }
630 2 : Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() );
631 2 : ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize );
632 2 : ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight );
633 : }
634 : }
635 0 : else if ( ( rGraphic.GetType() == GRAPHIC_GDIMETAFILE ) && nImageResolution )
636 : {
637 0 : VirtualDevice aDummyVDev;
638 0 : GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
639 0 : Size aMtfSize( OutputDevice::LogicToLogic( aMtf.GetPrefSize(), aMtf.GetPrefMapMode(), MAP_100TH_MM ) );
640 0 : if ( aMtfSize.Width() && aMtfSize.Height() )
641 : {
642 0 : MapMode aNewMapMode( MAP_100TH_MM );
643 0 : aNewMapMode.SetScaleX( static_cast< double >( aLogicalSize.Width ) / static_cast< double >( aMtfSize.Width() ) );
644 0 : aNewMapMode.SetScaleY( static_cast< double >( aLogicalSize.Height ) / static_cast< double >( aMtfSize.Height() ) );
645 0 : aDummyVDev.EnableOutput( false );
646 0 : aDummyVDev.SetMapMode( aNewMapMode );
647 :
648 0 : for( size_t i = 0, nObjCount = aMtf.GetActionSize(); i < nObjCount; i++ )
649 : {
650 0 : MetaAction* pAction = aMtf.GetAction( i );
651 0 : switch( pAction->GetType() )
652 : {
653 : // only optimizing common bitmap actions:
654 : case( META_MAPMODE_ACTION ):
655 : {
656 0 : const_cast< MetaAction* >( pAction )->Execute( &aDummyVDev );
657 0 : break;
658 : }
659 : case( META_PUSH_ACTION ):
660 : {
661 0 : const MetaPushAction* pA = static_cast<const MetaPushAction*>(pAction);
662 0 : aDummyVDev.Push( pA->GetFlags() );
663 0 : break;
664 : }
665 : case( META_POP_ACTION ):
666 : {
667 0 : aDummyVDev.Pop();
668 0 : break;
669 : }
670 : case( META_BMPSCALE_ACTION ):
671 : case( META_BMPEXSCALE_ACTION ):
672 : {
673 0 : BitmapEx aBmpEx;
674 0 : Point aPos;
675 0 : Size aSize;
676 0 : if ( pAction->GetType() == META_BMPSCALE_ACTION )
677 : {
678 0 : MetaBmpScaleAction* pScaleAction = dynamic_cast< MetaBmpScaleAction* >( pAction );
679 0 : aBmpEx = pScaleAction->GetBitmap();
680 0 : aPos = pScaleAction->GetPoint();
681 0 : aSize = pScaleAction->GetSize();
682 : }
683 : else
684 : {
685 0 : MetaBmpExScaleAction* pScaleAction = dynamic_cast< MetaBmpExScaleAction* >( pAction );
686 0 : aBmpEx = pScaleAction->GetBitmapEx();
687 0 : aPos = pScaleAction->GetPoint();
688 0 : aSize = pScaleAction->GetSize();
689 : }
690 0 : ::Graphic aGraphic( aBmpEx );
691 0 : const Size aSize100thmm( aDummyVDev.LogicToPixel( aSize ) );
692 0 : Size aSize100thmm2( aDummyVDev.PixelToLogic( aSize100thmm, MAP_100TH_MM ) );
693 :
694 : ImplApplyBitmapResolution( aGraphic, nImageResolution,
695 0 : aGraphic.GetSizePixel(), awt::Size( aSize100thmm2.Width(), aSize100thmm2.Height() ) );
696 :
697 : MetaAction* pNewAction;
698 0 : if ( pAction->GetType() == META_BMPSCALE_ACTION )
699 0 : pNewAction = new MetaBmpScaleAction ( aPos, aSize, aGraphic.GetBitmap() );
700 : else
701 0 : pNewAction = new MetaBmpExScaleAction( aPos, aSize, aGraphic.GetBitmapEx() );
702 :
703 0 : MetaAction* pDeleteAction = aMtf.ReplaceAction( pNewAction, i );
704 0 : if(pDeleteAction)
705 0 : pDeleteAction->Delete();
706 0 : break;
707 : }
708 : default:
709 : case( META_BMP_ACTION ):
710 : case( META_BMPSCALEPART_ACTION ):
711 : case( META_BMPEX_ACTION ):
712 : case( META_BMPEXSCALEPART_ACTION ):
713 : case( META_MASK_ACTION ):
714 : case( META_MASKSCALE_ACTION ):
715 0 : break;
716 : }
717 : }
718 0 : rGraphic = aMtf;
719 0 : }
720 : }
721 2 : }
722 :
723 :
724 :
725 2 : void SAL_CALL GraphicProvider::storeGraphic( const uno::Reference< ::graphic::XGraphic >& rxGraphic, const uno::Sequence< beans::PropertyValue >& rMediaProperties )
726 : throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
727 : {
728 2 : SolarMutexGuard g;
729 :
730 4 : boost::scoped_ptr<SvStream> pOStm;
731 4 : OUString aPath;
732 : sal_Int32 i;
733 :
734 6 : for( i = 0; ( i < rMediaProperties.getLength() ) && !pOStm; ++i )
735 : {
736 4 : const OUString aName( rMediaProperties[ i ].Name );
737 8 : const uno::Any aValue( rMediaProperties[ i ].Value );
738 :
739 4 : if (aName == "URL")
740 : {
741 0 : OUString aURL;
742 :
743 0 : aValue >>= aURL;
744 0 : pOStm.reset(::utl::UcbStreamHelper::CreateStream( aURL, STREAM_WRITE | STREAM_TRUNC ));
745 0 : aPath = aURL;
746 : }
747 4 : else if (aName == "OutputStream")
748 : {
749 2 : uno::Reference< io::XStream > xOStm;
750 :
751 2 : aValue >>= xOStm;
752 :
753 2 : if( xOStm.is() )
754 2 : pOStm.reset(::utl::UcbStreamHelper::CreateStream( xOStm ));
755 : }
756 4 : }
757 :
758 2 : if( pOStm )
759 : {
760 2 : uno::Sequence< beans::PropertyValue > aFilterDataSeq;
761 2 : const char* pFilterShortName = NULL;
762 :
763 6 : for( i = 0; i < rMediaProperties.getLength(); ++i )
764 : {
765 4 : const OUString aName( rMediaProperties[ i ].Name );
766 8 : const uno::Any aValue( rMediaProperties[ i ].Value );
767 :
768 4 : if (aName == "FilterData")
769 : {
770 0 : aValue >>= aFilterDataSeq;
771 : }
772 4 : else if (aName == "MimeType")
773 : {
774 2 : OUString aMimeType;
775 :
776 2 : aValue >>= aMimeType;
777 :
778 2 : if (aMimeType == MIMETYPE_BMP)
779 0 : pFilterShortName = "bmp";
780 2 : else if (aMimeType == MIMETYPE_EPS)
781 0 : pFilterShortName = "eps";
782 2 : else if (aMimeType == MIMETYPE_GIF)
783 0 : pFilterShortName = "gif";
784 2 : else if (aMimeType == MIMETYPE_JPG)
785 0 : pFilterShortName = "jpg";
786 2 : else if (aMimeType == MIMETYPE_MET)
787 0 : pFilterShortName = "met";
788 2 : else if (aMimeType == MIMETYPE_PNG)
789 2 : pFilterShortName = "png";
790 0 : else if (aMimeType == MIMETYPE_PCT)
791 0 : pFilterShortName = "pct";
792 0 : else if (aMimeType == MIMETYPE_PBM)
793 0 : pFilterShortName = "pbm";
794 0 : else if (aMimeType == MIMETYPE_PGM)
795 0 : pFilterShortName = "pgm";
796 0 : else if (aMimeType == MIMETYPE_PPM)
797 0 : pFilterShortName = "ppm";
798 0 : else if (aMimeType == MIMETYPE_RAS)
799 0 : pFilterShortName = "ras";
800 0 : else if (aMimeType == MIMETYPE_SVM)
801 0 : pFilterShortName = "svm";
802 0 : else if (aMimeType == MIMETYPE_TIF)
803 0 : pFilterShortName = "tif";
804 0 : else if (aMimeType == MIMETYPE_EMF)
805 0 : pFilterShortName = "emf";
806 0 : else if (aMimeType == MIMETYPE_WMF)
807 0 : pFilterShortName = "wmf";
808 0 : else if (aMimeType == MIMETYPE_XPM)
809 0 : pFilterShortName = "xpm";
810 0 : else if (aMimeType == MIMETYPE_SVG)
811 0 : pFilterShortName = "svg";
812 0 : else if (aMimeType == MIMETYPE_VCLGRAPHIC)
813 0 : pFilterShortName = MIMETYPE_VCLGRAPHIC;
814 : }
815 4 : }
816 :
817 2 : if( pFilterShortName )
818 : {
819 2 : ::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter();
820 :
821 : {
822 2 : const uno::Reference< XInterface > xIFace( rxGraphic, uno::UNO_QUERY );
823 2 : const ::Graphic* pGraphic = ::unographic::Graphic::getImplementation( xIFace );
824 :
825 2 : if( pGraphic && ( pGraphic->GetType() != GRAPHIC_NONE ) )
826 : {
827 2 : ::Graphic aGraphic( *pGraphic );
828 2 : ImplApplyFilterData( aGraphic, aFilterDataSeq );
829 :
830 : /* sj: using a temporary memory stream, because some graphic filters are seeking behind
831 : stream end (which leads to an invalid argument exception then). */
832 4 : SvMemoryStream aMemStrm;
833 2 : aMemStrm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
834 2 : if( 0 == strcmp( pFilterShortName, MIMETYPE_VCLGRAPHIC ) )
835 0 : WriteGraphic( aMemStrm, aGraphic );
836 : else
837 : {
838 : rFilter.ExportGraphic( aGraphic, aPath, aMemStrm,
839 4 : rFilter.GetExportFormatNumberForShortName( OUString::createFromAscii( pFilterShortName ) ),
840 4 : ( aFilterDataSeq.getLength() ? &aFilterDataSeq : NULL ) );
841 : }
842 2 : aMemStrm.Seek( STREAM_SEEK_TO_END );
843 4 : pOStm->Write( aMemStrm.GetData(), aMemStrm.Tell() );
844 2 : }
845 : }
846 2 : }
847 2 : }
848 2 : }
849 :
850 : }
851 :
852 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
853 145945 : com_sun_star_comp_graphic_GraphicProvider_get_implementation(
854 : css::uno::XComponentContext *,
855 : css::uno::Sequence<css::uno::Any> const &)
856 : {
857 145945 : return cppu::acquire(new GraphicProvider);
858 1227 : }
859 :
860 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|