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