xref: /trunk/main/svtools/source/graphic/provider.cxx (revision ddde725d)
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         if(rGraphic.getSvgData().get())
632         {
633             // embedded Svg, no need to scale. Also no method to apply crop data currently
634         }
635         else
636         {
637 		    Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() );
638 		    ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel );
639 		    if ( bRemoveCropArea )
640 		    {
641 			    BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
642 			    aBmpEx.Crop( aCropPixel );
643 			    rGraphic = aBmpEx;
644 		    }
645 		    Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() );
646 		    ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize );
647 		    ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight );
648         }
649 	}
650 	else if ( ( rGraphic.GetType() == GRAPHIC_GDIMETAFILE ) && nImageResolution )
651 	{
652 		VirtualDevice aDummyVDev;
653 		GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
654 		Size aMtfSize( aDummyVDev.LogicToLogic( aMtf.GetPrefSize(), aMtf.GetPrefMapMode(), MAP_100TH_MM ) );
655 		if ( aMtfSize.Width() && aMtfSize.Height() )
656 		{
657 			MapMode aNewMapMode( MAP_100TH_MM );
658 			aNewMapMode.SetScaleX( static_cast< double >( aLogicalSize.Width ) / static_cast< double >( aMtfSize.Width() ) );
659 			aNewMapMode.SetScaleY( static_cast< double >( aLogicalSize.Height ) / static_cast< double >( aMtfSize.Height() ) );
660 			aDummyVDev.EnableOutput( sal_False );
661 			aDummyVDev.SetMapMode( aNewMapMode );
662 
663 			for( sal_uInt32 i = 0, nObjCount = aMtf.GetActionCount(); i < nObjCount; i++ )
664 			{
665 				MetaAction* pAction = aMtf.GetAction( i );
666 				switch( pAction->GetType() )
667 				{
668 					// only optimizing common bitmap actions:
669 					case( META_MAPMODE_ACTION ):
670 					{
671 						const_cast< MetaAction* >( pAction )->Execute( &aDummyVDev );
672 						break;
673 					}
674 					case( META_PUSH_ACTION ):
675 					{
676 						const MetaPushAction* pA = (const MetaPushAction*)pAction;
677 						aDummyVDev.Push( pA->GetFlags() );
678 						break;
679 					}
680 					case( META_POP_ACTION ):
681 					{
682 						aDummyVDev.Pop();
683 						break;
684 					}
685 					case( META_BMPSCALE_ACTION ):
686 					case( META_BMPEXSCALE_ACTION ):
687 					{
688 						BitmapEx aBmpEx;
689 						Point aPos;
690 						Size aSize;
691 						if ( pAction->GetType() == META_BMPSCALE_ACTION )
692 						{
693 							MetaBmpScaleAction* pScaleAction = dynamic_cast< MetaBmpScaleAction* >( pAction );
694 							aBmpEx = pScaleAction->GetBitmap();
695 							aPos = pScaleAction->GetPoint();
696 							aSize = pScaleAction->GetSize();
697 						}
698 						else
699 						{
700 							MetaBmpExScaleAction* pScaleAction = dynamic_cast< MetaBmpExScaleAction* >( pAction );
701 							aBmpEx = pScaleAction->GetBitmapEx();
702 							aPos = pScaleAction->GetPoint();
703 							aSize = pScaleAction->GetSize();
704 						}
705 						::Graphic aGraphic( aBmpEx );
706 						const Size aSize100thmm( aDummyVDev.LogicToPixel( aSize ) );
707 						Size aSize100thmm2( aDummyVDev.PixelToLogic( aSize100thmm, MAP_100TH_MM ) );
708 
709 						ImplApplyBitmapResolution( aGraphic, nImageResolution,
710 							aGraphic.GetSizePixel(), awt::Size( aSize100thmm2.Width(), aSize100thmm2.Height() ) );
711 
712 						MetaAction* pNewAction;
713 						if ( pAction->GetType() == META_BMPSCALE_ACTION )
714 							pNewAction = new MetaBmpScaleAction ( aPos, aSize, aGraphic.GetBitmap() );
715 						else
716 							pNewAction = new MetaBmpExScaleAction( aPos, aSize, aGraphic.GetBitmapEx() );
717 
718 						aMtf.ReplaceAction( pNewAction, i );
719 						pAction->Delete();
720 						break;
721 					}
722 					default:
723 					case( META_BMP_ACTION ):
724 					case( META_BMPSCALEPART_ACTION ):
725 					case( META_BMPEX_ACTION ):
726 					case( META_BMPEXSCALEPART_ACTION ):
727 					case( META_MASK_ACTION ):
728 					case( META_MASKSCALE_ACTION ):
729 					break;
730 				}
731 			}
732 			rGraphic = aMtf;
733 		}
734 	}
735 }
736 
737 // ------------------------------------------------------------------------------
738 
739 void SAL_CALL GraphicProvider::storeGraphic( const uno::Reference< ::graphic::XGraphic >& rxGraphic, const uno::Sequence< beans::PropertyValue >& rMediaProperties )
740 	throw ( io::IOException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
741 {
742 	SvStream* 	pOStm = NULL;
743 	String		aPath;
744 	sal_Int32 	i;
745 
746 	for( i = 0; ( i < rMediaProperties.getLength() ) && !pOStm; ++i )
747 	{
748 		const ::rtl::OUString	aName( rMediaProperties[ i ].Name );
749 		const uno::Any 			aValue( rMediaProperties[ i ].Value );
750 
751 		if( COMPARE_EQUAL == aName.compareToAscii( "URL" ) )
752 		{
753 			::rtl::OUString aURL;
754 
755 			aValue >>= aURL;
756 			pOStm = ::utl::UcbStreamHelper::CreateStream( aURL, STREAM_WRITE | STREAM_TRUNC );
757 			aPath = aURL;
758 		}
759 		else if( COMPARE_EQUAL == aName.compareToAscii( "OutputStream" ) )
760 		{
761 			uno::Reference< io::XStream > xOStm;
762 
763 			aValue >>= xOStm;
764 
765 			if( xOStm.is() )
766 				pOStm = ::utl::UcbStreamHelper::CreateStream( xOStm );
767 		}
768 	}
769 
770 	if( pOStm )
771 	{
772 		uno::Sequence< beans::PropertyValue >	aFilterDataSeq;
773 		const char*								pFilterShortName = NULL;
774 
775 		for( i = 0; i < rMediaProperties.getLength(); ++i )
776 		{
777 			const ::rtl::OUString	aName( rMediaProperties[ i ].Name );
778 			const uno::Any 			aValue( rMediaProperties[ i ].Value );
779 
780 			if( COMPARE_EQUAL == aName.compareToAscii( "FilterData" ) )
781 			{
782 				aValue >>= aFilterDataSeq;
783 			}
784 			else if( COMPARE_EQUAL == aName.compareToAscii( "MimeType" ) )
785 			{
786 				::rtl::OUString aMimeType;
787 
788 				aValue >>= aMimeType;
789 
790 				if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_BMP ) )
791 					pFilterShortName = "bmp";
792 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_EPS ) )
793 					pFilterShortName = "eps";
794 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_GIF ) )
795 					pFilterShortName = "gif";
796 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_JPG ) )
797 					pFilterShortName = "jpg";
798 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_MET ) )
799 					pFilterShortName = "met";
800 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PNG ) )
801 					pFilterShortName = "png";
802 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PCT ) )
803 					pFilterShortName = "pct";
804 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PBM ) )
805 					pFilterShortName = "pbm";
806 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PGM ) )
807 					pFilterShortName = "pgm";
808 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_PPM ) )
809 					pFilterShortName = "ppm";
810 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_RAS ) )
811 					pFilterShortName = "ras";
812 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_SVM ) )
813 					pFilterShortName = "svm";
814 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_TIF ) )
815 					pFilterShortName = "tif";
816 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_EMF ) )
817 					pFilterShortName = "emf";
818 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_WMF ) )
819 					pFilterShortName = "wmf";
820 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_XPM ) )
821 					pFilterShortName = "xpm";
822 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_SVG ) )
823 					pFilterShortName = "svg";
824 				else if( COMPARE_EQUAL == aMimeType.compareToAscii( MIMETYPE_VCLGRAPHIC ) )
825 					pFilterShortName = MIMETYPE_VCLGRAPHIC;
826 			}
827 		}
828 
829 		if( pFilterShortName )
830 		{
831 			::GraphicFilter* pFilter = ::GraphicFilter::GetGraphicFilter();
832 
833 			if( pFilter )
834 			{
835 				const uno::Reference< XInterface > 	xIFace( rxGraphic, uno::UNO_QUERY );
836 				const ::Graphic* 					pGraphic = ::unographic::Graphic::getImplementation( xIFace );
837 
838 				if( pGraphic && ( pGraphic->GetType() != GRAPHIC_NONE ) )
839 				{
840 					::Graphic aGraphic( *pGraphic );
841 					ImplApplyFilterData( aGraphic, aFilterDataSeq );
842 
843 					/* sj: using a temporary memory stream, because some graphic filters are seeking behind
844 					   stream end (which leads to an invalid argument exception then). */
845 					SvMemoryStream aMemStrm;
846 					aMemStrm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
847 					if( 0 == strcmp( pFilterShortName, MIMETYPE_VCLGRAPHIC ) )
848 						aMemStrm << aGraphic;
849 					else
850 					{
851 						pFilter->ExportGraphic( aGraphic, aPath, aMemStrm,
852 												pFilter->GetExportFormatNumberForShortName( ::rtl::OUString::createFromAscii( pFilterShortName ) ),
853 													( aFilterDataSeq.getLength() ? &aFilterDataSeq : NULL ) );
854 					}
855 					aMemStrm.Seek( STREAM_SEEK_TO_END );
856 					pOStm->Write( aMemStrm.GetData(), aMemStrm.Tell() );
857 				}
858 			}
859 		}
860 		delete pOStm;
861 	}
862 }
863 
864 }
865