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