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