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