Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / doc / graphhelp.cxx
blobe7ec525d7eaa30d9bac9372d47089972ced12e36
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 ************************************************************************/
30 #ifdef WNT
32 #undef WB_LEFT
33 #undef WB_RIGHT
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>
41 #if defined _MSC_VER
42 #pragma warning(push, 1)
43 #endif
44 #include <windows.h>
45 #if defined _MSC_VER
46 #pragma warning(pop)
47 #endif
48 #include <tools/postsys.h>
50 #undef UINT64
51 #undef INT64
52 #undef UINT32
53 #undef INT32
55 #endif
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"
83 #include "doc.hrc"
85 using namespace ::com::sun::star;
87 #define THUMBNAIL_RESOLUTION 256
89 //---------------------------------------------------------------
90 // static
91 SvMemoryStream* GraphicHelper::getFormatStrFromGDI_Impl( const GDIMetaFile* pGDIMeta, sal_uInt32 nFormat )
93 SvMemoryStream* pResult = NULL;
94 if ( pGDIMeta )
96 SvMemoryStream* pStream = new SvMemoryStream( 65535, 65535 );
97 if ( pStream )
99 Graphic aGraph( *pGDIMeta );
100 if ( GraphicConverter::Export( *pStream, aGraph, nFormat ) == 0 )
101 pResult = pStream;
102 else
103 delete pStream;
107 return pResult;
110 //---------------------------------------------------------------
111 // static
112 void* GraphicHelper::getEnhMetaFileFromGDI_Impl( const GDIMetaFile* pGDIMeta )
114 (void)pGDIMeta; // unused
115 void* pResult = NULL;
117 #ifdef WNT
118 if ( pGDIMeta )
120 String aStr = ::rtl::OUString(".emf");
121 ::utl::TempFile aTempFile( ::rtl::OUString(),
122 &aStr,
123 NULL,
124 sal_False );
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 );
131 if ( pStream )
133 Graphic aGraph( *pGDIMeta );
134 sal_Bool bFailed = (sal_Bool)GraphicConverter::Export( *pStream, aGraph, CVT_EMF );
135 pStream->Flush();
136 delete pStream;
138 if ( !bFailed )
139 pResult = GetEnhMetaFileA( aWinFile.getStr() );
142 #endif
144 return pResult;
147 //---------------------------------------------------------------
148 // static
149 void* GraphicHelper::getWinMetaFileFromGDI_Impl( const GDIMetaFile* pGDIMeta, const Size& aMetaSize )
151 (void)pGDIMeta; // unused
152 (void)aMetaSize; // unused
153 void* pResult = NULL;
155 #ifdef WNT
156 if ( pGDIMeta )
158 SvMemoryStream* pStream = new SvMemoryStream( 65535, 65535 );
159 if ( pStream )
161 Graphic aGraph( *pGDIMeta );
162 sal_Bool bFailed = (sal_Bool)GraphicConverter::Export( *pStream, aGraph, CVT_WMF );
163 pStream->Flush();
164 if ( !bFailed )
166 sal_Int32 nLength = pStream->Seek( STREAM_SEEK_TO_END );
167 if ( nLength > 22 )
169 HMETAFILE hMeta = SetMetaFileBitsEx( nLength - 22,
170 ( reinterpret_cast< const sal_uChar*>( pStream->GetData() ) ) + 22 );
172 if ( hMeta )
174 HGLOBAL hMemory = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, sizeof( METAFILEPICT ) );
176 if ( hMemory )
178 METAFILEPICT* pMF = (METAFILEPICT*)GlobalLock( hMemory );
180 pMF->hMF = hMeta;
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();
191 else
193 Size aWinSize = OutputDevice::LogicToLogic( Size( aMetaSize.Width(), aMetaSize.Height() ),
194 pGDIMeta->GetPrefMapMode(),
195 aWinMode );
196 pMF->xExt = aWinSize.Width();
197 pMF->yExt = aWinSize.Height();
200 GlobalUnlock( hMemory );
201 pResult = (void*)hMemory;
203 else
204 DeleteMetaFile( hMeta );
209 delete pStream;
213 #endif
216 return pResult;
219 //---------------------------------------------------------------
220 // static
221 sal_Bool GraphicHelper::supportsMetaFileHandle_Impl()
223 #ifdef WNT
224 return sal_True;
225 #else
226 return sal_False;
227 #endif
230 //---------------------------------------------------------------
231 // static
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
237 Point aNullPt;
238 Rectangle aBmpRect( aNullPt, rBmpEx.GetSizePixel() );
239 VirtualDevice aVDev;
241 if( !rReturn.IsEmpty() )
242 rReturn.SetEmpty();
244 if( !rBmpEx.IsEmpty() && aVDev.SetOutputSizePixel( aBmpRect.GetSize() ) )
246 Rectangle aOverlayRect( rOverlayRect );
248 aOverlayRect.Intersection( aBmpRect );
250 if( rOverlay.IsEmpty() || rOverlayRect.IsEmpty() )
251 rReturn = rBmpEx;
252 else
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() )
261 rReturn = aBmp;
262 else
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() );
269 else
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 //---------------------------------------------------------------
288 // static
289 sal_Bool GraphicHelper::createThumb_Impl( const GDIMetaFile& rMtf,
290 sal_uInt32 nMaximumExtent,
291 BitmapEx& rBmpEx,
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
298 VirtualDevice aVDev;
299 const Point aNullPt;
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 );
304 Point aPosPix;
306 if ( !rBmpEx.IsEmpty() )
307 rBmpEx.SetEmpty();
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();
318 if ( fWH <= 1.0 )
320 aSizePix.Width() = FRound( nMaximumExtent * fWH );
321 aSizePix.Height() = nMaximumExtent;
323 else
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() );
333 Size aFullSize;
334 Point aBackPosPix;
335 Rectangle aOverlayRect;
337 // calculate addigtional positions and sizes if an overlay image is used
338 if ( pOverlay )
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 );
347 else
348 pOverlay = NULL;
350 else
352 aFullSize = aSizePix;
353 pOverlay = NULL;
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
364 if ( pOverlay )
365 aVDev.DrawBitmapEx( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), *pOverlay );
367 // get paint bitmap
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 //---------------------------------------------------------------
381 // static
382 sal_Bool GraphicHelper::getThumbnailFormatFromGDI_Impl( GDIMetaFile* pMetaFile,
383 sal_Bool bSigned,
384 const uno::Reference< io::XStream >& xStream )
386 sal_Bool bResult = sal_False;
387 SvStream* pStream = NULL;
389 if ( xStream.is() )
390 pStream = ::utl::UcbStreamHelper::CreateStream( xStream );
392 if ( pMetaFile && pStream && !pStream->GetError() )
394 BitmapEx aResultBitmap;
395 BitmapEx* pSignatureBitmap = NULL;
397 if ( bSigned )
398 pSignatureBitmap = new BitmapEx( SfxResId( BMP_SIGNATURE ) );
400 bResult = createThumb_Impl( *pMetaFile,
401 THUMBNAIL_RESOLUTION,
402 aResultBitmap,
403 pSignatureBitmap );
404 if ( bResult )
405 bResult = ( !aResultBitmap.IsEmpty()
406 && GraphicConverter::Export( *pStream, aResultBitmap, CVT_PNG ) == 0
407 && ( pStream->Flush(), !pStream->GetError() ) );
409 if ( pSignatureBitmap )
410 delete pSignatureBitmap;
412 delete pStream;
415 return bResult;
418 //---------------------------------------------------------------
419 // static
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;
426 if ( xStream.is() )
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,
435 aSignatureBitmap,
436 Rectangle( Point(), aBitmap.GetSizePixel() ),
437 aResultBitmap );
439 if ( bResult )
441 bResult = ( !aResultBitmap.IsEmpty()
442 && GraphicConverter::Export( *pStream, aResultBitmap, CVT_PNG ) == 0
443 && ( pStream->Flush(), !pStream->GetError() ) );
446 delete pStream;
449 return bResult;
452 //---------------------------------------------------------------
453 // static
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 );
471 if ( xGraphic.is() )
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 );
480 bResult = sal_True;
483 catch(const uno::Exception&)
488 return bResult;
491 //---------------------------------------------------------------
492 // static
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;
518 return nResult;
521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */