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 <tools/fract.hxx>
30 : #include <unotools/ucbstreamhelper.hxx>
31 : #include <vcl/graphicfilter.hxx>
32 : #include <vcl/wmf.hxx>
33 : #include <svl/solar.hrc>
34 : #include <vcl/virdev.hxx>
35 : #include <vcl/settings.hxx>
36 : #include <com/sun/star/io/XStream.hpp>
37 : #include <com/sun/star/text/GraphicCrop.hpp>
38 : #include <com/sun/star/uno/XComponentContext.hpp>
39 : #include <comphelper/servicehelper.hxx>
40 : #include <cppuhelper/supportsservice.hxx>
41 :
42 : #include "descriptor.hxx"
43 : #include "graphic.hxx"
44 : #include <rtl/ref.hxx>
45 : #include <svtools/grfmgr.hxx>
46 : #include "provider.hxx"
47 : #include <vcl/dibtools.hxx>
48 : #include <boost/scoped_ptr.hpp>
49 :
50 : using namespace com::sun::star;
51 :
52 : namespace {
53 :
54 : #define UNO_NAME_GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:"
55 :
56 86406 : GraphicProvider::GraphicProvider()
57 : {
58 86406 : }
59 :
60 172810 : GraphicProvider::~GraphicProvider()
61 : {
62 172810 : }
63 :
64 1 : OUString SAL_CALL GraphicProvider::getImplementationName()
65 : throw( uno::RuntimeException, std::exception )
66 : {
67 1 : return OUString( "com.sun.star.comp.graphic.GraphicProvider" );
68 : }
69 :
70 0 : sal_Bool SAL_CALL GraphicProvider::supportsService( const OUString& ServiceName )
71 : throw( uno::RuntimeException, std::exception )
72 : {
73 0 : return cppu::supportsService( this, ServiceName );
74 : }
75 :
76 1 : uno::Sequence< OUString > SAL_CALL GraphicProvider::getSupportedServiceNames()
77 : throw( uno::RuntimeException, std::exception )
78 : {
79 1 : uno::Sequence< OUString > aSeq( 1 );
80 1 : aSeq.getArray()[ 0 ] = "com.sun.star.graphic.GraphicProvider";
81 1 : return aSeq;
82 : }
83 :
84 0 : uno::Sequence< uno::Type > SAL_CALL GraphicProvider::getTypes()
85 : throw(uno::RuntimeException, std::exception)
86 : {
87 0 : uno::Sequence< uno::Type > aTypes( 3 );
88 0 : uno::Type* pTypes = aTypes.getArray();
89 :
90 0 : *pTypes++ = cppu::UnoType<lang::XServiceInfo>::get();
91 0 : *pTypes++ = cppu::UnoType<lang::XTypeProvider>::get();
92 0 : *pTypes++ = cppu::UnoType<graphic::XGraphicProvider>::get();
93 :
94 0 : return aTypes;
95 : }
96 :
97 0 : uno::Sequence< sal_Int8 > SAL_CALL GraphicProvider::getImplementationId()
98 : throw(uno::RuntimeException, std::exception)
99 : {
100 0 : return css::uno::Sequence<sal_Int8>();
101 : }
102 :
103 :
104 :
105 4103 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadGraphicObject( const OUString& rResourceURL )
106 : {
107 4103 : uno::Reference< ::graphic::XGraphic > xRet;
108 4103 : if( rResourceURL.startsWith( UNO_NAME_GRAPHOBJ_URLPREFIX ) )
109 : {
110 : // graphic manager url
111 278 : OUString aTmpStr( rResourceURL.copy( sizeof( UNO_NAME_GRAPHOBJ_URLPREFIX ) - 1 ) );
112 : OString aUniqueID(OUStringToOString(aTmpStr,
113 556 : RTL_TEXTENCODING_UTF8));
114 556 : GraphicObject aGrafObj(aUniqueID);
115 : // I don't call aGrafObj.GetXGraphic because it will call us back
116 : // into implLoadMemory ( with "private:memorygraphic" test )
117 278 : ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
118 278 : pUnoGraphic->init( aGrafObj.GetGraphic() );
119 556 : xRet = pUnoGraphic;
120 : }
121 4103 : return xRet;
122 : }
123 :
124 84030 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadMemory( const OUString& rResourceURL )
125 : {
126 84030 : uno::Reference< ::graphic::XGraphic > xRet;
127 84030 : sal_Int32 nIndex = 0;
128 :
129 84030 : if( rResourceURL.getToken( 0, '/', nIndex ) == "private:memorygraphic" )
130 : {
131 79927 : sal_Int64 nGraphicAddress = rResourceURL.getToken( 0, '/', nIndex ).toInt64();
132 :
133 79927 : if( nGraphicAddress )
134 : {
135 79927 : ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
136 :
137 79927 : pUnoGraphic->init( *reinterpret_cast< ::Graphic* >( nGraphicAddress ) );
138 79927 : xRet = pUnoGraphic;
139 : }
140 : }
141 :
142 84030 : return xRet;
143 : }
144 :
145 :
146 :
147 3825 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadRepositoryImage( const OUString& rResourceURL )
148 : {
149 3825 : uno::Reference< ::graphic::XGraphic > xRet;
150 3825 : sal_Int32 nIndex = 0;
151 :
152 3825 : if( rResourceURL.getToken( 0, '/', nIndex ) == "private:graphicrepository" )
153 : {
154 3796 : OUString sPathName( rResourceURL.copy( nIndex ) );
155 7592 : BitmapEx aBitmap;
156 3796 : if ( vcl::ImageRepository::loadImage( sPathName, aBitmap, false ) )
157 : {
158 3796 : Image aImage( aBitmap );
159 3796 : xRet = aImage.GetXGraphic();
160 3796 : }
161 : }
162 3825 : return xRet;
163 : }
164 :
165 :
166 :
167 :
168 29 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadStandardImage( const OUString& rResourceURL )
169 : {
170 29 : uno::Reference< ::graphic::XGraphic > xRet;
171 29 : sal_Int32 nIndex = 0;
172 :
173 29 : if( rResourceURL.getToken( 0, '/', nIndex ) == "private:standardimage" )
174 : {
175 0 : OUString sImageName( rResourceURL.copy( nIndex ) );
176 0 : if ( sImageName == "info" )
177 : {
178 0 : xRet = InfoBox::GetStandardImage().GetXGraphic();
179 : }
180 0 : else if ( sImageName == "warning" )
181 : {
182 0 : xRet = WarningBox::GetStandardImage().GetXGraphic();
183 : }
184 0 : else if ( sImageName == "error" )
185 : {
186 0 : xRet = ErrorBox::GetStandardImage().GetXGraphic();
187 : }
188 0 : else if ( sImageName == "query" )
189 : {
190 0 : xRet = QueryBox::GetStandardImage().GetXGraphic();
191 0 : }
192 : }
193 29 : return xRet;
194 : }
195 :
196 :
197 :
198 0 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadBitmap( const uno::Reference< awt::XBitmap >& xBtm )
199 : {
200 0 : uno::Reference< ::graphic::XGraphic > xRet;
201 0 : uno::Sequence< sal_Int8 > aBmpSeq( xBtm->getDIB() );
202 0 : uno::Sequence< sal_Int8 > aMaskSeq( xBtm->getMaskDIB() );
203 0 : SvMemoryStream aBmpStream( aBmpSeq.getArray(), aBmpSeq.getLength(), StreamMode::READ );
204 0 : Bitmap aBmp;
205 0 : BitmapEx aBmpEx;
206 :
207 0 : ReadDIB(aBmp, aBmpStream, true);
208 :
209 0 : if( aMaskSeq.getLength() )
210 : {
211 0 : SvMemoryStream aMaskStream( aMaskSeq.getArray(), aMaskSeq.getLength(), StreamMode::READ );
212 0 : Bitmap aMask;
213 :
214 0 : ReadDIB(aMask, aMaskStream, true);
215 0 : aBmpEx = BitmapEx( aBmp, aMask );
216 : }
217 : else
218 0 : aBmpEx = BitmapEx( aBmp );
219 :
220 0 : if( !aBmpEx.IsEmpty() )
221 : {
222 0 : ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
223 :
224 0 : pUnoGraphic->init( aBmpEx );
225 0 : xRet = pUnoGraphic;
226 : }
227 0 : return xRet;
228 : }
229 :
230 :
231 :
232 3825 : uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadResource( const OUString& rResourceURL )
233 : {
234 3825 : uno::Reference< ::graphic::XGraphic > xRet;
235 3825 : sal_Int32 nIndex = 0;
236 :
237 3825 : if( rResourceURL.getToken( 0, '/', nIndex ) == "private:resource" )
238 : {
239 : OString aResMgrName(OUStringToOString(
240 0 : rResourceURL.getToken(0, '/', nIndex), RTL_TEXTENCODING_ASCII_US));
241 :
242 0 : boost::scoped_ptr<ResMgr> pResMgr(ResMgr::CreateResMgr( aResMgrName.getStr(), Application::GetSettings().GetUILanguageTag() ));
243 :
244 0 : if( pResMgr )
245 : {
246 0 : const OUString aResourceType( rResourceURL.getToken( 0, '/', nIndex ) );
247 0 : const ResId aResId( rResourceURL.getToken( 0, '/', nIndex ).toInt32(), *pResMgr );
248 :
249 0 : if( !aResourceType.isEmpty() )
250 : {
251 0 : BitmapEx aBmpEx;
252 :
253 0 : if( aResourceType == "bitmap" || aResourceType == "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 == "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 == "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 3825 : 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 84661 : 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 84661 : uno::Reference< ::graphic::XGraphic > xRet;
386 169322 : OUString aPath;
387 169322 : boost::scoped_ptr<SvStream> pIStm;
388 :
389 169322 : uno::Reference< io::XInputStream > xIStm;
390 169322 : uno::Reference< awt::XBitmap >xBtm;
391 :
392 169322 : uno::Sequence< ::beans::PropertyValue > aFilterData;
393 :
394 169329 : for( sal_Int32 i = 0; ( i < rMediaProperties.getLength() ) && !pIStm && !xRet.is(); ++i )
395 : {
396 84668 : const OUString aName( rMediaProperties[ i ].Name );
397 169336 : const uno::Any aValue( rMediaProperties[ i ].Value );
398 :
399 84668 : if (aName == "URL")
400 : {
401 84116 : OUString aURL;
402 84116 : aValue >>= aURL;
403 84116 : aPath = aURL;
404 : }
405 552 : else if (aName == "InputStream")
406 : {
407 545 : aValue >>= xIStm;
408 : }
409 7 : else if (aName == "Bitmap")
410 : {
411 0 : aValue >>= xBtm;
412 : }
413 7 : else if (aName == "FilterData")
414 : {
415 7 : aValue >>= aFilterData;
416 : }
417 84668 : }
418 :
419 : // Check for the goal width and height if they are defined
420 84661 : sal_uInt16 nExtWidth = 0;
421 84661 : sal_uInt16 nExtHeight = 0;
422 84661 : sal_uInt16 nExtMapMode = 0;
423 84682 : for( sal_Int32 i = 0; i < aFilterData.getLength(); ++i )
424 : {
425 21 : const OUString aName( aFilterData[ i ].Name );
426 42 : const uno::Any aValue( aFilterData[ i ].Value );
427 :
428 21 : if (aName == "ExternalWidth")
429 : {
430 7 : aValue >>= nExtWidth;
431 : }
432 14 : else if (aName == "ExternalHeight")
433 : {
434 7 : aValue >>= nExtHeight;
435 : }
436 7 : else if (aName == "ExternalMapMode")
437 : {
438 7 : aValue >>= nExtMapMode;
439 : }
440 21 : }
441 :
442 169322 : SolarMutexGuard g;
443 :
444 84661 : if( xIStm.is() )
445 : {
446 545 : pIStm.reset(::utl::UcbStreamHelper::CreateStream( xIStm ));
447 : }
448 84116 : else if( !aPath.isEmpty() )
449 : {
450 84030 : xRet = implLoadMemory( aPath );
451 :
452 84030 : if( !xRet.is() )
453 4103 : xRet = implLoadGraphicObject( aPath );
454 :
455 84030 : if( !xRet.is() )
456 3825 : xRet = implLoadResource( aPath );
457 :
458 84030 : if ( !xRet.is() )
459 3825 : xRet = implLoadRepositoryImage( aPath );
460 :
461 84030 : if ( !xRet.is() )
462 29 : xRet = implLoadStandardImage( aPath );
463 :
464 84030 : if( !xRet.is() )
465 29 : pIStm.reset(::utl::UcbStreamHelper::CreateStream( aPath, StreamMode::READ ));
466 : }
467 86 : else if( xBtm.is() )
468 : {
469 0 : xRet = implLoadBitmap( xBtm );
470 : }
471 :
472 84661 : if( pIStm )
473 : {
474 574 : ::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter();
475 :
476 : {
477 574 : ::Graphic aVCLGraphic;
478 :
479 : // Define APM Header if goal height and width are defined
480 574 : WMF_EXTERNALHEADER aExtHeader;
481 574 : aExtHeader.xExt = nExtWidth;
482 574 : aExtHeader.yExt = nExtHeight;
483 574 : aExtHeader.mapMode = nExtMapMode;
484 574 : WMF_EXTERNALHEADER *pExtHeader = NULL;
485 574 : if ( nExtMapMode > 0 )
486 7 : pExtHeader = &aExtHeader;
487 :
488 1148 : if( ( rFilter.ImportGraphic( aVCLGraphic, aPath, *pIStm,
489 1118 : GRFILTER_FORMAT_DONTKNOW, NULL, GraphicFilterImportFlags::NONE, pExtHeader ) == GRFILTER_OK ) &&
490 544 : ( aVCLGraphic.GetType() != GRAPHIC_NONE ) )
491 : {
492 544 : ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic;
493 :
494 544 : pUnoGraphic->init( aVCLGraphic );
495 544 : xRet = pUnoGraphic;
496 574 : }
497 : }
498 : }
499 :
500 169322 : return xRet;
501 : }
502 :
503 1 : void ImplCalculateCropRect( ::Graphic& rGraphic, const text::GraphicCrop& rGraphicCropLogic, Rectangle& rGraphicCropPixel )
504 : {
505 1 : 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 1 : }
534 :
535 1 : void ImplApplyBitmapScaling( ::Graphic& rGraphic, sal_Int32 nPixelWidth, sal_Int32 nPixelHeight )
536 : {
537 1 : 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 1 : }
548 :
549 1 : void ImplApplyBitmapResolution( ::Graphic& rGraphic, sal_Int32 nImageResolution, const Size& rVisiblePixelSize, const awt::Size& rLogicalSize )
550 : {
551 1 : 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 1 : }
581 :
582 1 : 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 1 : sal_Int32 nPixelWidth = 0;
590 1 : sal_Int32 nPixelHeight= 0;
591 1 : sal_Int32 nImageResolution = 0;
592 1 : awt::Size aLogicalSize( 0, 0 );
593 1 : text::GraphicCrop aCropLogic( 0, 0, 0, 0 );
594 1 : bool bRemoveCropArea = true;
595 :
596 1 : 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 1 : if ( rGraphic.GetType() == GRAPHIC_BITMAP )
615 : {
616 1 : 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 1 : Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() );
623 1 : ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel );
624 1 : if ( bRemoveCropArea )
625 : {
626 1 : BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
627 1 : aBmpEx.Crop( aCropPixel );
628 1 : rGraphic = aBmpEx;
629 : }
630 1 : Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() );
631 1 : ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize );
632 1 : ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight );
633 : }
634 : }
635 0 : else if ( ( rGraphic.GetType() == GRAPHIC_GDIMETAFILE ) && nImageResolution )
636 : {
637 0 : ScopedVclPtrInstance< 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( MetaActionType::MAPMODE ):
655 : {
656 0 : pAction->Execute( aDummyVDev.get() );
657 0 : break;
658 : }
659 : case( MetaActionType::PUSH ):
660 : {
661 0 : const MetaPushAction* pA = static_cast<const MetaPushAction*>(pAction);
662 0 : aDummyVDev->Push( pA->GetFlags() );
663 0 : break;
664 : }
665 : case( MetaActionType::POP ):
666 : {
667 0 : aDummyVDev->Pop();
668 0 : break;
669 : }
670 : case( MetaActionType::BMPSCALE ):
671 : case( MetaActionType::BMPEXSCALE ):
672 : {
673 0 : BitmapEx aBmpEx;
674 0 : Point aPos;
675 0 : Size aSize;
676 0 : if ( pAction->GetType() == MetaActionType::BMPSCALE )
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() == MetaActionType::BMPSCALE )
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( MetaActionType::BMP ):
710 : case( MetaActionType::BMPSCALEPART ):
711 : case( MetaActionType::BMPEX ):
712 : case( MetaActionType::BMPEXSCALEPART ):
713 : case( MetaActionType::MASK ):
714 : case( MetaActionType::MASKSCALE ):
715 0 : break;
716 : }
717 : }
718 0 : rGraphic = aMtf;
719 0 : }
720 : }
721 1 : }
722 :
723 :
724 :
725 1 : 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 1 : SolarMutexGuard g;
729 :
730 2 : boost::scoped_ptr<SvStream> pOStm;
731 2 : OUString aPath;
732 : sal_Int32 i;
733 :
734 3 : for( i = 0; ( i < rMediaProperties.getLength() ) && !pOStm; ++i )
735 : {
736 2 : const OUString aName( rMediaProperties[ i ].Name );
737 4 : const uno::Any aValue( rMediaProperties[ i ].Value );
738 :
739 2 : if (aName == "URL")
740 : {
741 0 : OUString aURL;
742 :
743 0 : aValue >>= aURL;
744 0 : pOStm.reset(::utl::UcbStreamHelper::CreateStream( aURL, StreamMode::WRITE | StreamMode::TRUNC ));
745 0 : aPath = aURL;
746 : }
747 2 : else if (aName == "OutputStream")
748 : {
749 1 : uno::Reference< io::XStream > xOStm;
750 :
751 1 : aValue >>= xOStm;
752 :
753 1 : if( xOStm.is() )
754 1 : pOStm.reset(::utl::UcbStreamHelper::CreateStream( xOStm ));
755 : }
756 2 : }
757 :
758 1 : if( pOStm )
759 : {
760 1 : uno::Sequence< beans::PropertyValue > aFilterDataSeq;
761 1 : const char* pFilterShortName = NULL;
762 :
763 3 : for( i = 0; i < rMediaProperties.getLength(); ++i )
764 : {
765 2 : const OUString aName( rMediaProperties[ i ].Name );
766 4 : const uno::Any aValue( rMediaProperties[ i ].Value );
767 :
768 2 : if (aName == "FilterData")
769 : {
770 0 : aValue >>= aFilterDataSeq;
771 : }
772 2 : else if (aName == "MimeType")
773 : {
774 1 : OUString aMimeType;
775 :
776 1 : aValue >>= aMimeType;
777 :
778 1 : if (aMimeType == MIMETYPE_BMP)
779 0 : pFilterShortName = "bmp";
780 1 : else if (aMimeType == MIMETYPE_EPS)
781 0 : pFilterShortName = "eps";
782 1 : else if (aMimeType == MIMETYPE_GIF)
783 0 : pFilterShortName = "gif";
784 1 : else if (aMimeType == MIMETYPE_JPG)
785 0 : pFilterShortName = "jpg";
786 1 : else if (aMimeType == MIMETYPE_MET)
787 0 : pFilterShortName = "met";
788 1 : else if (aMimeType == MIMETYPE_PNG)
789 1 : 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 2 : }
816 :
817 1 : if( pFilterShortName )
818 : {
819 1 : ::GraphicFilter& rFilter = ::GraphicFilter::GetGraphicFilter();
820 :
821 : {
822 1 : const uno::Reference< XInterface > xIFace( rxGraphic, uno::UNO_QUERY );
823 1 : const ::Graphic* pGraphic = ::unographic::Graphic::getImplementation( xIFace );
824 :
825 1 : if( pGraphic && ( pGraphic->GetType() != GRAPHIC_NONE ) )
826 : {
827 1 : ::Graphic aGraphic( *pGraphic );
828 1 : 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 2 : SvMemoryStream aMemStrm;
833 1 : aMemStrm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
834 1 : if( 0 == strcmp( pFilterShortName, MIMETYPE_VCLGRAPHIC ) )
835 0 : WriteGraphic( aMemStrm, aGraphic );
836 : else
837 : {
838 : rFilter.ExportGraphic( aGraphic, aPath, aMemStrm,
839 2 : rFilter.GetExportFormatNumberForShortName( OUString::createFromAscii( pFilterShortName ) ),
840 2 : ( aFilterDataSeq.getLength() ? &aFilterDataSeq : NULL ) );
841 : }
842 1 : aMemStrm.Seek( STREAM_SEEK_TO_END );
843 2 : pOStm->Write( aMemStrm.GetData(), aMemStrm.Tell() );
844 1 : }
845 : }
846 1 : }
847 1 : }
848 1 : }
849 :
850 : }
851 :
852 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
853 86406 : com_sun_star_comp_graphic_GraphicProvider_get_implementation(
854 : css::uno::XComponentContext *,
855 : css::uno::Sequence<css::uno::Any> const &)
856 : {
857 86406 : return cppu::acquire(new GraphicProvider);
858 798 : }
859 :
860 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|