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