1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: graphhelp.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
39 #define UINT64 USE_WIN_UINT64
40 #define INT64 USE_WIN_INT64
41 #define UINT32 USE_WIN_UINT32
42 #define INT32 USE_WIN_INT32
44 #include <tools/presys.h>
46 #pragma warning(push, 1)
52 #include <tools/postsys.h>
60 #include <com/sun/star/uno/Exception.hpp>
61 #include <com/sun/star/datatransfer/XTransferable.hpp>
62 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
63 #include <com/sun/star/graphic/XGraphicProvider.hpp>
64 #include <com/sun/star/graphic/XGraphic.hpp>
65 #include <com/sun/star/io/XStream.hpp>
68 #include <osl/thread.h>
69 #include <vcl/gdimtf.hxx>
70 #include <vcl/graph.hxx>
71 #include <vcl/cvtgrf.hxx>
72 #include <vcl/outdev.hxx>
73 #include <vcl/virdev.hxx>
74 #include <vcl/bitmapex.hxx>
75 #include <vcl/salbtype.hxx>
77 #include <tools/stream.hxx>
78 #include <unotools/tempfile.hxx>
79 #include <unotools/ucbstreamhelper.hxx>
80 #include <unotools/streamwrap.hxx>
81 #include <comphelper/processfactory.hxx>
84 #include "sfxresid.hxx"
85 #include "graphhelp.hxx"
88 using namespace ::com::sun::star
;
90 #define THUMBNAIL_RESOLUTION 256
92 //---------------------------------------------------------------
94 SvMemoryStream
* GraphicHelper::getFormatStrFromGDI_Impl( const GDIMetaFile
* pGDIMeta
, sal_uInt32 nFormat
)
96 SvMemoryStream
* pResult
= NULL
;
99 SvMemoryStream
* pStream
= new SvMemoryStream( 65535, 65535 );
102 Graphic
aGraph( *pGDIMeta
);
103 if ( GraphicConverter::Export( *pStream
, aGraph
, nFormat
) == 0 )
113 //---------------------------------------------------------------
115 void* GraphicHelper::getEnhMetaFileFromGDI_Impl( const GDIMetaFile
* pGDIMeta
)
117 (void)pGDIMeta
; // unused
118 void* pResult
= NULL
;
123 String aStr
= ::rtl::OUString::createFromAscii( ".emf" );
124 ::utl::TempFile
aTempFile( ::rtl::OUString(),
129 ::rtl::OUString aMetaFile
= aTempFile
.GetFileName();
130 ::rtl::OUString aMetaURL
= aTempFile
.GetURL();
131 ::rtl::OString aWinFile
= ::rtl::OUStringToOString( aMetaFile
, osl_getThreadTextEncoding() );
133 SvStream
* pStream
= ::utl::UcbStreamHelper::CreateStream( aMetaURL
, STREAM_STD_READWRITE
);
136 Graphic
aGraph( *pGDIMeta
);
137 sal_Bool bFailed
= (sal_Bool
)GraphicConverter::Export( *pStream
, aGraph
, CVT_EMF
);
142 pResult
= GetEnhMetaFileA( aWinFile
.getStr() );
150 //---------------------------------------------------------------
152 void* GraphicHelper::getWinMetaFileFromGDI_Impl( const GDIMetaFile
* pGDIMeta
, const Size
& aMetaSize
)
154 (void)pGDIMeta
; // unused
155 (void)aMetaSize
; // unused
156 void* pResult
= NULL
;
161 SvMemoryStream
* pStream
= new SvMemoryStream( 65535, 65535 );
164 Graphic
aGraph( *pGDIMeta
);
165 sal_Bool bFailed
= (sal_Bool
)GraphicConverter::Export( *pStream
, aGraph
, CVT_WMF
);
169 sal_Int32 nLength
= pStream
->Seek( STREAM_SEEK_TO_END
);
172 HMETAFILE hMeta
= SetMetaFileBitsEx( nLength
- 22,
173 ( reinterpret_cast< const sal_uChar
*>( pStream
->GetData() ) ) + 22 );
177 HGLOBAL hMemory
= GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, sizeof( METAFILEPICT
) );
181 METAFILEPICT
* pMF
= (METAFILEPICT
*)GlobalLock( hMemory
);
184 pMF
->mm
= MM_ANISOTROPIC
;
186 MapMode aMetaMode
= pGDIMeta
->GetPrefMapMode();
187 MapMode
aWinMode( MAP_100TH_MM
);
189 if ( aWinMode
== pGDIMeta
->GetPrefMapMode() )
191 pMF
->xExt
= aMetaSize
.Width();
192 pMF
->yExt
= aMetaSize
.Height();
196 Size aWinSize
= OutputDevice::LogicToLogic( Size( aMetaSize
.Width(), aMetaSize
.Height() ),
197 pGDIMeta
->GetPrefMapMode(),
199 pMF
->xExt
= aWinSize
.Width();
200 pMF
->yExt
= aWinSize
.Height();
203 GlobalUnlock( hMemory
);
204 pResult
= (void*)hMemory
;
207 DeleteMetaFile( hMeta
);
222 //---------------------------------------------------------------
224 sal_Bool
GraphicHelper::supportsMetaFileHandle_Impl()
233 //---------------------------------------------------------------
235 sal_Bool
GraphicHelper::mergeBitmaps_Impl( const BitmapEx
& rBmpEx
, const BitmapEx
& rOverlay
,
236 const Rectangle
& rOverlayRect
, BitmapEx
& rReturn
)
238 // the implementation is provided by KA
241 Rectangle
aBmpRect( aNullPt
, rBmpEx
.GetSizePixel() );
244 if( !rReturn
.IsEmpty() )
247 if( !rBmpEx
.IsEmpty() && aVDev
.SetOutputSizePixel( aBmpRect
.GetSize() ) )
249 Rectangle
aOverlayRect( rOverlayRect
);
251 aOverlayRect
.Intersection( aBmpRect
);
253 if( rOverlay
.IsEmpty() || rOverlayRect
.IsEmpty() )
257 aVDev
.DrawBitmap( aNullPt
, aVDev
.GetOutputSizePixel(), rBmpEx
.GetBitmap() );
258 aVDev
.DrawBitmapEx( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize(), rOverlay
);
260 Bitmap
aBmp( aVDev
.GetBitmap( aNullPt
, aVDev
.GetOutputSizePixel() ) );
261 aBmp
.Convert( BMP_CONVERSION_24BIT
);
263 if( !rBmpEx
.IsTransparent() )
267 aVDev
.DrawBitmap( aNullPt
, aVDev
.GetOutputSizePixel(), rBmpEx
.GetMask() );
268 Bitmap
aOverlayMergeBmp( aVDev
.GetBitmap( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize() ) );
270 if( rOverlay
.IsTransparent() )
271 aVDev
.DrawBitmap( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize(), rOverlay
.GetMask() );
274 aVDev
.SetLineColor( COL_BLACK
);
275 aVDev
.SetFillColor( COL_BLACK
);
276 aVDev
.DrawRect( aOverlayRect
);
279 aOverlayMergeBmp
.CombineSimple( aVDev
.GetBitmap( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize() ), BMP_COMBINE_AND
);
280 aVDev
.DrawBitmap( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize(), aOverlayMergeBmp
);
281 rReturn
= BitmapEx( aBmp
, aVDev
.GetBitmap( aNullPt
, aVDev
.GetOutputSizePixel() ) );
286 return !rReturn
.IsEmpty();
290 //---------------------------------------------------------------
292 sal_Bool
GraphicHelper::createThumb_Impl( const GDIMetaFile
& rMtf
,
293 sal_uInt32 nMaximumExtent
,
295 const BitmapEx
* pOverlay
,
296 const Rectangle
* pOverlayRect
)
298 // the implementation is provided by KA
300 // initialization seems to be complicated but is used to avoid rounding errors
303 const Point
aTLPix( aVDev
.LogicToPixel( aNullPt
, rMtf
.GetPrefMapMode() ) );
304 const Point
aBRPix( aVDev
.LogicToPixel( Point( rMtf
.GetPrefSize().Width() - 1, rMtf
.GetPrefSize().Height() - 1 ), rMtf
.GetPrefMapMode() ) );
305 Size
aDrawSize( aVDev
.LogicToPixel( rMtf
.GetPrefSize(), rMtf
.GetPrefMapMode() ) );
306 Size
aSizePix( labs( aBRPix
.X() - aTLPix
.X() ) + 1, labs( aBRPix
.Y() - aTLPix
.Y() ) + 1 );
309 if ( !rBmpEx
.IsEmpty() )
312 // determine size that has the same aspect ratio as image size and
313 // fits into the rectangle determined by nMaximumExtent
314 if ( aSizePix
.Width() && aSizePix
.Height() &&
315 ( sal::static_int_cast
<sal_uInt32
>(aSizePix
.Width()) > nMaximumExtent
||
316 sal::static_int_cast
<sal_uInt32
>(aSizePix
.Height()) > nMaximumExtent
) )
318 const Size
aOldSizePix( aSizePix
);
319 double fWH
= static_cast< double >( aSizePix
.Width() ) / aSizePix
.Height();
323 aSizePix
.Width() = FRound( nMaximumExtent
* fWH
);
324 aSizePix
.Height() = nMaximumExtent
;
328 aSizePix
.Width() = nMaximumExtent
;
329 aSizePix
.Height() = FRound( nMaximumExtent
/ fWH
);
332 aDrawSize
.Width() = FRound( ( static_cast< double >( aDrawSize
.Width() ) * aSizePix
.Width() ) / aOldSizePix
.Width() );
333 aDrawSize
.Height() = FRound( ( static_cast< double >( aDrawSize
.Height() ) * aSizePix
.Height() ) / aOldSizePix
.Height() );
338 Rectangle aOverlayRect
;
340 // calculate addigtional positions and sizes if an overlay image is used
343 aFullSize
= Size( nMaximumExtent
, nMaximumExtent
);
344 aOverlayRect
= Rectangle( aNullPt
, aFullSize
);
346 aOverlayRect
.Intersection( pOverlayRect
? *pOverlayRect
: Rectangle( aNullPt
, pOverlay
->GetSizePixel() ) );
348 if ( !aOverlayRect
.IsEmpty() )
349 aBackPosPix
= Point( ( nMaximumExtent
- aSizePix
.Width() ) >> 1, ( nMaximumExtent
- aSizePix
.Height() ) >> 1 );
355 aFullSize
= aSizePix
;
359 // draw image(s) into VDev and get resulting image
360 if ( aVDev
.SetOutputSizePixel( aFullSize
) )
362 // draw metafile into VDev
363 const_cast< GDIMetaFile
& >( rMtf
).WindStart();
364 const_cast< GDIMetaFile
& >( rMtf
).Play( &aVDev
, aBackPosPix
, aDrawSize
);
366 // draw overlay if neccessary
368 aVDev
.DrawBitmapEx( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize(), *pOverlay
);
371 Bitmap
aBmp( aVDev
.GetBitmap( aNullPt
, aVDev
.GetOutputSizePixel() ) );
373 // assure that we have a true color image
374 if ( aBmp
.GetBitCount() != 24 )
375 aBmp
.Convert( BMP_CONVERSION_24BIT
);
377 rBmpEx
= BitmapEx( aBmp
);
380 return !rBmpEx
.IsEmpty();
383 //---------------------------------------------------------------
385 sal_Bool
GraphicHelper::getThumbnailFormatFromGDI_Impl( GDIMetaFile
* pMetaFile
,
387 const uno::Reference
< io::XStream
>& xStream
)
389 sal_Bool bResult
= sal_False
;
390 SvStream
* pStream
= NULL
;
393 pStream
= ::utl::UcbStreamHelper::CreateStream( xStream
);
395 if ( pMetaFile
&& pStream
&& !pStream
->GetError() )
397 BitmapEx aResultBitmap
;
398 BitmapEx
* pSignatureBitmap
= NULL
;
401 pSignatureBitmap
= new BitmapEx( SfxResId( BMP_SIGNATURE
) );
403 bResult
= createThumb_Impl( *pMetaFile
,
404 THUMBNAIL_RESOLUTION
,
408 bResult
= ( !aResultBitmap
.IsEmpty()
409 && GraphicConverter::Export( *pStream
, aResultBitmap
, CVT_PNG
) == 0
410 && ( pStream
->Flush(), !pStream
->GetError() ) );
412 if ( pSignatureBitmap
)
413 delete pSignatureBitmap
;
421 //---------------------------------------------------------------
423 sal_Bool
GraphicHelper::getSignedThumbnailFormatFromBitmap_Impl( const BitmapEx
& aBitmap
,
424 const uno::Reference
< io::XStream
>& xStream
)
426 sal_Bool bResult
= sal_False
;
427 SvStream
* pStream
= NULL
;
430 pStream
= ::utl::UcbStreamHelper::CreateStream( xStream
);
432 if ( pStream
&& !pStream
->GetError() )
434 BitmapEx aResultBitmap
;
435 BitmapEx
aSignatureBitmap( SfxResId( BMP_SIGNATURE
) );
437 bResult
= mergeBitmaps_Impl( aBitmap
,
439 Rectangle( Point(), aBitmap
.GetSizePixel() ),
444 bResult
= ( !aResultBitmap
.IsEmpty()
445 && GraphicConverter::Export( *pStream
, aResultBitmap
, CVT_PNG
) == 0
446 && ( pStream
->Flush(), !pStream
->GetError() ) );
455 //---------------------------------------------------------------
457 sal_Bool
GraphicHelper::getThumbnailReplacement_Impl( sal_Int32 nResID
, const uno::Reference
< io::XStream
>& xStream
)
459 sal_Bool bResult
= sal_False
;
460 if ( nResID
&& xStream
.is() )
462 uno::Reference
< lang::XMultiServiceFactory
> xServiceManager
= ::comphelper::getProcessServiceFactory();
463 if ( xServiceManager
.is() )
467 uno::Reference
< graphic::XGraphicProvider
> xGraphProvider(
468 xServiceManager
->createInstance(
469 ::rtl::OUString::createFromAscii( "com.sun.star.graphic.GraphicProvider" ) ),
471 if ( xGraphProvider
.is() )
473 ::rtl::OUString aURL
= ::rtl::OUString::createFromAscii( "private:resource/sfx/bitmapex/" );
474 aURL
+= ::rtl::OUString::valueOf( nResID
);
476 uno::Sequence
< beans::PropertyValue
> aMediaProps( 1 );
477 aMediaProps
[0].Name
= ::rtl::OUString::createFromAscii( "URL" );
478 aMediaProps
[0].Value
<<= aURL
;
480 uno::Reference
< graphic::XGraphic
> xGraphic
= xGraphProvider
->queryGraphic( aMediaProps
);
483 uno::Sequence
< beans::PropertyValue
> aStoreProps( 2 );
484 aStoreProps
[0].Name
= ::rtl::OUString::createFromAscii( "OutputStream" );
485 aStoreProps
[0].Value
<<= xStream
;
486 aStoreProps
[1].Name
= ::rtl::OUString::createFromAscii( "MimeType" );
487 aStoreProps
[1].Value
<<= ::rtl::OUString::createFromAscii( "image/png" );
489 xGraphProvider
->storeGraphic( xGraphic
, aStoreProps
);
494 catch( uno::Exception
& )
503 //---------------------------------------------------------------
505 sal_uInt16
GraphicHelper::getThumbnailReplacementIDByFactoryName_Impl( const ::rtl::OUString
& aFactoryShortName
, sal_Bool
/*bIsTemplate*/ )
507 sal_uInt16 nResult
= 0;
509 if ( aFactoryShortName
.equalsAscii( "scalc" ) )
511 nResult
= BMP_128X128_CALC_DOC
;
513 else if ( aFactoryShortName
.equalsAscii( "sdraw" ) )
515 nResult
= BMP_128X128_DRAW_DOC
;
517 else if ( aFactoryShortName
.equalsAscii( "simpress" ) )
519 nResult
= BMP_128X128_IMPRESS_DOC
;
521 else if ( aFactoryShortName
.equalsAscii( "smath" ) )
523 nResult
= BMP_128X128_MATH_DOC
;
525 else if ( aFactoryShortName
.equalsAscii( "swriter" ) || aFactoryShortName
.compareToAscii( "swriter/", 8 ) == 0 )
527 nResult
= BMP_128X128_WRITER_DOC
;