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