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