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