xref: /trunk/main/svtools/source/graphic/provider.cxx (revision e1d5bd03a6ea7ac2b26b792c9e2a94e9f347a43b)
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