1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
35 #define UINT64 USE_WIN_UINT64
36 #define INT64 USE_WIN_INT64
37 #define UINT32 USE_WIN_UINT32
38 #define INT32 USE_WIN_INT32
40 #include <tools/presys.h>
42 #pragma warning(push, 1)
48 #include <tools/postsys.h>
56 #include <com/sun/star/uno/Exception.hpp>
57 #include <com/sun/star/datatransfer/XTransferable.hpp>
58 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
59 #include <com/sun/star/graphic/GraphicProvider.hpp>
60 #include <com/sun/star/graphic/XGraphicProvider.hpp>
61 #include <com/sun/star/graphic/XGraphic.hpp>
62 #include <com/sun/star/io/XStream.hpp>
65 #include <osl/thread.h>
66 #include <vcl/gdimtf.hxx>
67 #include <vcl/graph.hxx>
68 #include <vcl/cvtgrf.hxx>
69 #include <vcl/outdev.hxx>
70 #include <vcl/virdev.hxx>
71 #include <vcl/bitmapex.hxx>
72 #include <vcl/salbtype.hxx>
74 #include <tools/stream.hxx>
75 #include <unotools/tempfile.hxx>
76 #include <unotools/ucbstreamhelper.hxx>
77 #include <unotools/streamwrap.hxx>
78 #include <comphelper/processfactory.hxx>
81 #include "sfx2/sfxresid.hxx"
82 #include "graphhelp.hxx"
85 using namespace ::com::sun::star
;
87 #define THUMBNAIL_RESOLUTION 256
89 //---------------------------------------------------------------
91 SvMemoryStream
* GraphicHelper::getFormatStrFromGDI_Impl( const GDIMetaFile
* pGDIMeta
, sal_uInt32 nFormat
)
93 SvMemoryStream
* pResult
= NULL
;
96 SvMemoryStream
* pStream
= new SvMemoryStream( 65535, 65535 );
99 Graphic
aGraph( *pGDIMeta
);
100 if ( GraphicConverter::Export( *pStream
, aGraph
, nFormat
) == 0 )
110 //---------------------------------------------------------------
112 void* GraphicHelper::getEnhMetaFileFromGDI_Impl( const GDIMetaFile
* pGDIMeta
)
114 (void)pGDIMeta
; // unused
115 void* pResult
= NULL
;
120 String aStr
= ::rtl::OUString(".emf");
121 ::utl::TempFile
aTempFile( ::rtl::OUString(),
126 ::rtl::OUString aMetaFile
= aTempFile
.GetFileName();
127 ::rtl::OUString aMetaURL
= aTempFile
.GetURL();
128 ::rtl::OString aWinFile
= ::rtl::OUStringToOString( aMetaFile
, osl_getThreadTextEncoding() );
130 SvStream
* pStream
= ::utl::UcbStreamHelper::CreateStream( aMetaURL
, STREAM_STD_READWRITE
);
133 Graphic
aGraph( *pGDIMeta
);
134 sal_Bool bFailed
= (sal_Bool
)GraphicConverter::Export( *pStream
, aGraph
, CVT_EMF
);
139 pResult
= GetEnhMetaFileA( aWinFile
.getStr() );
147 //---------------------------------------------------------------
149 void* GraphicHelper::getWinMetaFileFromGDI_Impl( const GDIMetaFile
* pGDIMeta
, const Size
& aMetaSize
)
151 (void)pGDIMeta
; // unused
152 (void)aMetaSize
; // unused
153 void* pResult
= NULL
;
158 SvMemoryStream
* pStream
= new SvMemoryStream( 65535, 65535 );
161 Graphic
aGraph( *pGDIMeta
);
162 sal_Bool bFailed
= (sal_Bool
)GraphicConverter::Export( *pStream
, aGraph
, CVT_WMF
);
166 sal_Int32 nLength
= pStream
->Seek( STREAM_SEEK_TO_END
);
169 HMETAFILE hMeta
= SetMetaFileBitsEx( nLength
- 22,
170 ( reinterpret_cast< const sal_uChar
*>( pStream
->GetData() ) ) + 22 );
174 HGLOBAL hMemory
= GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, sizeof( METAFILEPICT
) );
178 METAFILEPICT
* pMF
= (METAFILEPICT
*)GlobalLock( hMemory
);
181 pMF
->mm
= MM_ANISOTROPIC
;
183 MapMode aMetaMode
= pGDIMeta
->GetPrefMapMode();
184 MapMode
aWinMode( MAP_100TH_MM
);
186 if ( aWinMode
== pGDIMeta
->GetPrefMapMode() )
188 pMF
->xExt
= aMetaSize
.Width();
189 pMF
->yExt
= aMetaSize
.Height();
193 Size aWinSize
= OutputDevice::LogicToLogic( Size( aMetaSize
.Width(), aMetaSize
.Height() ),
194 pGDIMeta
->GetPrefMapMode(),
196 pMF
->xExt
= aWinSize
.Width();
197 pMF
->yExt
= aWinSize
.Height();
200 GlobalUnlock( hMemory
);
201 pResult
= (void*)hMemory
;
204 DeleteMetaFile( hMeta
);
219 //---------------------------------------------------------------
221 sal_Bool
GraphicHelper::supportsMetaFileHandle_Impl()
230 //---------------------------------------------------------------
232 sal_Bool
GraphicHelper::mergeBitmaps_Impl( const BitmapEx
& rBmpEx
, const BitmapEx
& rOverlay
,
233 const Rectangle
& rOverlayRect
, BitmapEx
& rReturn
)
235 // the implementation is provided by KA
238 Rectangle
aBmpRect( aNullPt
, rBmpEx
.GetSizePixel() );
241 if( !rReturn
.IsEmpty() )
244 if( !rBmpEx
.IsEmpty() && aVDev
.SetOutputSizePixel( aBmpRect
.GetSize() ) )
246 Rectangle
aOverlayRect( rOverlayRect
);
248 aOverlayRect
.Intersection( aBmpRect
);
250 if( rOverlay
.IsEmpty() || rOverlayRect
.IsEmpty() )
254 aVDev
.DrawBitmap( aNullPt
, aVDev
.GetOutputSizePixel(), rBmpEx
.GetBitmap() );
255 aVDev
.DrawBitmapEx( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize(), rOverlay
);
257 Bitmap
aBmp( aVDev
.GetBitmap( aNullPt
, aVDev
.GetOutputSizePixel() ) );
258 aBmp
.Convert( BMP_CONVERSION_24BIT
);
260 if( !rBmpEx
.IsTransparent() )
264 aVDev
.DrawBitmap( aNullPt
, aVDev
.GetOutputSizePixel(), rBmpEx
.GetMask() );
265 Bitmap
aOverlayMergeBmp( aVDev
.GetBitmap( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize() ) );
267 if( rOverlay
.IsTransparent() )
268 aVDev
.DrawBitmap( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize(), rOverlay
.GetMask() );
271 aVDev
.SetLineColor( COL_BLACK
);
272 aVDev
.SetFillColor( COL_BLACK
);
273 aVDev
.DrawRect( aOverlayRect
);
276 aOverlayMergeBmp
.CombineSimple( aVDev
.GetBitmap( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize() ), BMP_COMBINE_AND
);
277 aVDev
.DrawBitmap( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize(), aOverlayMergeBmp
);
278 rReturn
= BitmapEx( aBmp
, aVDev
.GetBitmap( aNullPt
, aVDev
.GetOutputSizePixel() ) );
283 return !rReturn
.IsEmpty();
287 //---------------------------------------------------------------
289 sal_Bool
GraphicHelper::createThumb_Impl( const GDIMetaFile
& rMtf
,
290 sal_uInt32 nMaximumExtent
,
292 const BitmapEx
* pOverlay
,
293 const Rectangle
* pOverlayRect
)
295 // the implementation is provided by KA
297 // initialization seems to be complicated but is used to avoid rounding errors
300 const Point
aTLPix( aVDev
.LogicToPixel( aNullPt
, rMtf
.GetPrefMapMode() ) );
301 const Point
aBRPix( aVDev
.LogicToPixel( Point( rMtf
.GetPrefSize().Width() - 1, rMtf
.GetPrefSize().Height() - 1 ), rMtf
.GetPrefMapMode() ) );
302 Size
aDrawSize( aVDev
.LogicToPixel( rMtf
.GetPrefSize(), rMtf
.GetPrefMapMode() ) );
303 Size
aSizePix( labs( aBRPix
.X() - aTLPix
.X() ) + 1, labs( aBRPix
.Y() - aTLPix
.Y() ) + 1 );
306 if ( !rBmpEx
.IsEmpty() )
309 // determine size that has the same aspect ratio as image size and
310 // fits into the rectangle determined by nMaximumExtent
311 if ( aSizePix
.Width() && aSizePix
.Height() &&
312 ( sal::static_int_cast
<sal_uInt32
>(aSizePix
.Width()) > nMaximumExtent
||
313 sal::static_int_cast
<sal_uInt32
>(aSizePix
.Height()) > nMaximumExtent
) )
315 const Size
aOldSizePix( aSizePix
);
316 double fWH
= static_cast< double >( aSizePix
.Width() ) / aSizePix
.Height();
320 aSizePix
.Width() = FRound( nMaximumExtent
* fWH
);
321 aSizePix
.Height() = nMaximumExtent
;
325 aSizePix
.Width() = nMaximumExtent
;
326 aSizePix
.Height() = FRound( nMaximumExtent
/ fWH
);
329 aDrawSize
.Width() = FRound( ( static_cast< double >( aDrawSize
.Width() ) * aSizePix
.Width() ) / aOldSizePix
.Width() );
330 aDrawSize
.Height() = FRound( ( static_cast< double >( aDrawSize
.Height() ) * aSizePix
.Height() ) / aOldSizePix
.Height() );
335 Rectangle aOverlayRect
;
337 // calculate addigtional positions and sizes if an overlay image is used
340 aFullSize
= Size( nMaximumExtent
, nMaximumExtent
);
341 aOverlayRect
= Rectangle( aNullPt
, aFullSize
);
343 aOverlayRect
.Intersection( pOverlayRect
? *pOverlayRect
: Rectangle( aNullPt
, pOverlay
->GetSizePixel() ) );
345 if ( !aOverlayRect
.IsEmpty() )
346 aBackPosPix
= Point( ( nMaximumExtent
- aSizePix
.Width() ) >> 1, ( nMaximumExtent
- aSizePix
.Height() ) >> 1 );
352 aFullSize
= aSizePix
;
356 // draw image(s) into VDev and get resulting image
357 if ( aVDev
.SetOutputSizePixel( aFullSize
) )
359 // draw metafile into VDev
360 const_cast< GDIMetaFile
& >( rMtf
).WindStart();
361 const_cast< GDIMetaFile
& >( rMtf
).Play( &aVDev
, aBackPosPix
, aDrawSize
);
363 // draw overlay if neccessary
365 aVDev
.DrawBitmapEx( aOverlayRect
.TopLeft(), aOverlayRect
.GetSize(), *pOverlay
);
368 Bitmap
aBmp( aVDev
.GetBitmap( aNullPt
, aVDev
.GetOutputSizePixel() ) );
370 // assure that we have a true color image
371 if ( aBmp
.GetBitCount() != 24 )
372 aBmp
.Convert( BMP_CONVERSION_24BIT
);
374 rBmpEx
= BitmapEx( aBmp
);
377 return !rBmpEx
.IsEmpty();
380 //---------------------------------------------------------------
382 sal_Bool
GraphicHelper::getThumbnailFormatFromGDI_Impl( GDIMetaFile
* pMetaFile
,
384 const uno::Reference
< io::XStream
>& xStream
)
386 sal_Bool bResult
= sal_False
;
387 SvStream
* pStream
= NULL
;
390 pStream
= ::utl::UcbStreamHelper::CreateStream( xStream
);
392 if ( pMetaFile
&& pStream
&& !pStream
->GetError() )
394 BitmapEx aResultBitmap
;
395 BitmapEx
* pSignatureBitmap
= NULL
;
398 pSignatureBitmap
= new BitmapEx( SfxResId( BMP_SIGNATURE
) );
400 bResult
= createThumb_Impl( *pMetaFile
,
401 THUMBNAIL_RESOLUTION
,
405 bResult
= ( !aResultBitmap
.IsEmpty()
406 && GraphicConverter::Export( *pStream
, aResultBitmap
, CVT_PNG
) == 0
407 && ( pStream
->Flush(), !pStream
->GetError() ) );
409 if ( pSignatureBitmap
)
410 delete pSignatureBitmap
;
418 //---------------------------------------------------------------
420 sal_Bool
GraphicHelper::getSignedThumbnailFormatFromBitmap_Impl( const BitmapEx
& aBitmap
,
421 const uno::Reference
< io::XStream
>& xStream
)
423 sal_Bool bResult
= sal_False
;
424 SvStream
* pStream
= NULL
;
427 pStream
= ::utl::UcbStreamHelper::CreateStream( xStream
);
429 if ( pStream
&& !pStream
->GetError() )
431 BitmapEx aResultBitmap
;
432 BitmapEx
aSignatureBitmap( SfxResId( BMP_SIGNATURE
) );
434 bResult
= mergeBitmaps_Impl( aBitmap
,
436 Rectangle( Point(), aBitmap
.GetSizePixel() ),
441 bResult
= ( !aResultBitmap
.IsEmpty()
442 && GraphicConverter::Export( *pStream
, aResultBitmap
, CVT_PNG
) == 0
443 && ( pStream
->Flush(), !pStream
->GetError() ) );
452 //---------------------------------------------------------------
454 sal_Bool
GraphicHelper::getThumbnailReplacement_Impl( sal_Int32 nResID
, const uno::Reference
< io::XStream
>& xStream
)
456 sal_Bool bResult
= sal_False
;
457 if ( nResID
&& xStream
.is() )
459 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
462 uno::Reference
< graphic::XGraphicProvider
> xGraphProvider(graphic::GraphicProvider::create(xContext
));
463 ::rtl::OUString
aURL("private:resource/sfx/bitmapex/");
464 aURL
+= ::rtl::OUString::valueOf( nResID
);
466 uno::Sequence
< beans::PropertyValue
> aMediaProps( 1 );
467 aMediaProps
[0].Name
= "URL";
468 aMediaProps
[0].Value
<<= aURL
;
470 uno::Reference
< graphic::XGraphic
> xGraphic
= xGraphProvider
->queryGraphic( aMediaProps
);
473 uno::Sequence
< beans::PropertyValue
> aStoreProps( 2 );
474 aStoreProps
[0].Name
= "OutputStream";
475 aStoreProps
[0].Value
<<= xStream
;
476 aStoreProps
[1].Name
= "MimeType";
477 aStoreProps
[1].Value
<<= ::rtl::OUString("image/png");
479 xGraphProvider
->storeGraphic( xGraphic
, aStoreProps
);
483 catch(const uno::Exception
&)
491 //---------------------------------------------------------------
493 sal_uInt16
GraphicHelper::getThumbnailReplacementIDByFactoryName_Impl( const ::rtl::OUString
& aFactoryShortName
, sal_Bool
/*bIsTemplate*/ )
495 sal_uInt16 nResult
= 0;
497 if ( aFactoryShortName
== "scalc" )
499 nResult
= BMP_128X128_CALC_DOC
;
501 else if ( aFactoryShortName
== "sdraw" )
503 nResult
= BMP_128X128_DRAW_DOC
;
505 else if ( aFactoryShortName
== "simpress" )
507 nResult
= BMP_128X128_IMPRESS_DOC
;
509 else if ( aFactoryShortName
== "smath" )
511 nResult
= BMP_128X128_MATH_DOC
;
513 else if ( aFactoryShortName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "swriter" ) ) || aFactoryShortName
.compareToAscii( "swriter/", 8 ) == 0 )
515 nResult
= BMP_128X128_WRITER_DOC
;
521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */