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