bump product version to 4.1.6.2
[LibreOffice.git] / sfx2 / source / doc / graphhelp.cxx
blob8f3a5b528421df08b2ac7ff6d01cea992f6785d1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #ifdef WNT
23 #undef WB_LEFT
24 #undef WB_RIGHT
26 #define UINT64 USE_WIN_UINT64
27 #define INT64 USE_WIN_INT64
28 #define UINT32 USE_WIN_UINT32
29 #define INT32 USE_WIN_INT32
31 #include <tools/presys.h>
32 #if defined _MSC_VER
33 #pragma warning(push, 1)
34 #endif
35 #include <windows.h>
36 #if defined _MSC_VER
37 #pragma warning(pop)
38 #endif
39 #include <tools/postsys.h>
41 #undef UINT64
42 #undef INT64
43 #undef UINT32
44 #undef INT32
46 #endif
47 #include <com/sun/star/uno/Exception.hpp>
48 #include <com/sun/star/datatransfer/XTransferable.hpp>
49 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 #include <com/sun/star/graphic/GraphicProvider.hpp>
51 #include <com/sun/star/graphic/XGraphicProvider.hpp>
52 #include <com/sun/star/graphic/XGraphic.hpp>
53 #include <com/sun/star/io/XStream.hpp>
56 #include <osl/thread.h>
57 #include <vcl/gdimtf.hxx>
58 #include <vcl/graph.hxx>
59 #include <vcl/cvtgrf.hxx>
60 #include <vcl/outdev.hxx>
61 #include <vcl/virdev.hxx>
62 #include <vcl/bitmapex.hxx>
64 #include <tools/stream.hxx>
65 #include <tools/helpers.hxx>
66 #include <unotools/tempfile.hxx>
67 #include <unotools/ucbstreamhelper.hxx>
68 #include <unotools/streamwrap.hxx>
69 #include <comphelper/processfactory.hxx>
72 #include "sfx2/sfxresid.hxx"
73 #include "graphhelp.hxx"
74 #include "doc.hrc"
76 using namespace ::com::sun::star;
78 #define THUMBNAIL_RESOLUTION 256
80 //---------------------------------------------------------------
81 // static
82 SvMemoryStream* GraphicHelper::getFormatStrFromGDI_Impl( const GDIMetaFile* pGDIMeta, sal_uInt32 nFormat )
84 SvMemoryStream* pResult = NULL;
85 if ( pGDIMeta )
87 SvMemoryStream* pStream = new SvMemoryStream( 65535, 65535 );
88 if ( pStream )
90 Graphic aGraph( *pGDIMeta );
91 if ( GraphicConverter::Export( *pStream, aGraph, nFormat ) == 0 )
92 pResult = pStream;
93 else
94 delete pStream;
98 return pResult;
101 //---------------------------------------------------------------
102 // static
103 void* GraphicHelper::getEnhMetaFileFromGDI_Impl( const GDIMetaFile* pGDIMeta )
105 (void)pGDIMeta; // unused
106 void* pResult = NULL;
108 #ifdef WNT
109 if ( pGDIMeta )
111 String aStr = OUString(".emf");
112 ::utl::TempFile aTempFile( OUString(),
113 &aStr,
114 NULL,
115 sal_False );
117 OUString aMetaFile = aTempFile.GetFileName();
118 OUString aMetaURL = aTempFile.GetURL();
119 OString aWinFile = OUStringToOString( aMetaFile, osl_getThreadTextEncoding() );
121 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aMetaURL, STREAM_STD_READWRITE );
122 if ( pStream )
124 Graphic aGraph( *pGDIMeta );
125 sal_Bool bFailed = (sal_Bool)GraphicConverter::Export( *pStream, aGraph, CVT_EMF );
126 pStream->Flush();
127 delete pStream;
129 if ( !bFailed )
130 pResult = GetEnhMetaFileA( aWinFile.getStr() );
133 #endif
135 return pResult;
138 //---------------------------------------------------------------
139 // static
140 void* GraphicHelper::getWinMetaFileFromGDI_Impl( const GDIMetaFile* pGDIMeta, const Size& aMetaSize )
142 (void)pGDIMeta; // unused
143 (void)aMetaSize; // unused
144 void* pResult = NULL;
146 #ifdef WNT
147 if ( pGDIMeta )
149 SvMemoryStream* pStream = new SvMemoryStream( 65535, 65535 );
150 if ( pStream )
152 Graphic aGraph( *pGDIMeta );
153 sal_Bool bFailed = (sal_Bool)GraphicConverter::Export( *pStream, aGraph, CVT_WMF );
154 pStream->Flush();
155 if ( !bFailed )
157 sal_Int32 nLength = pStream->Seek( STREAM_SEEK_TO_END );
158 if ( nLength > 22 )
160 HMETAFILE hMeta = SetMetaFileBitsEx( nLength - 22,
161 ( reinterpret_cast< const sal_uChar*>( pStream->GetData() ) ) + 22 );
163 if ( hMeta )
165 HGLOBAL hMemory = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, sizeof( METAFILEPICT ) );
167 if ( hMemory )
169 METAFILEPICT* pMF = (METAFILEPICT*)GlobalLock( hMemory );
171 pMF->hMF = hMeta;
172 pMF->mm = MM_ANISOTROPIC;
174 MapMode aMetaMode = pGDIMeta->GetPrefMapMode();
175 MapMode aWinMode( MAP_100TH_MM );
177 if ( aWinMode == pGDIMeta->GetPrefMapMode() )
179 pMF->xExt = aMetaSize.Width();
180 pMF->yExt = aMetaSize.Height();
182 else
184 Size aWinSize = OutputDevice::LogicToLogic( Size( aMetaSize.Width(), aMetaSize.Height() ),
185 pGDIMeta->GetPrefMapMode(),
186 aWinMode );
187 pMF->xExt = aWinSize.Width();
188 pMF->yExt = aWinSize.Height();
191 GlobalUnlock( hMemory );
192 pResult = (void*)hMemory;
194 else
195 DeleteMetaFile( hMeta );
200 delete pStream;
204 #endif
207 return pResult;
210 //---------------------------------------------------------------
211 // static
212 sal_Bool GraphicHelper::supportsMetaFileHandle_Impl()
214 #ifdef WNT
215 return sal_True;
216 #else
217 return sal_False;
218 #endif
221 //---------------------------------------------------------------
222 // static
223 sal_Bool GraphicHelper::mergeBitmaps_Impl( const BitmapEx& rBmpEx, const BitmapEx& rOverlay,
224 const Rectangle& rOverlayRect, BitmapEx& rReturn )
226 // the implementation is provided by KA
228 Point aNullPt;
229 Rectangle aBmpRect( aNullPt, rBmpEx.GetSizePixel() );
230 VirtualDevice aVDev;
232 if( !rReturn.IsEmpty() )
233 rReturn.SetEmpty();
235 if( !rBmpEx.IsEmpty() && aVDev.SetOutputSizePixel( aBmpRect.GetSize() ) )
237 Rectangle aOverlayRect( rOverlayRect );
239 aOverlayRect.Intersection( aBmpRect );
241 if( rOverlay.IsEmpty() || rOverlayRect.IsEmpty() )
242 rReturn = rBmpEx;
243 else
245 aVDev.DrawBitmap( aNullPt, aVDev.GetOutputSizePixel(), rBmpEx.GetBitmap() );
246 aVDev.DrawBitmapEx( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), rOverlay );
248 Bitmap aBmp( aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() ) );
249 aBmp.Convert( BMP_CONVERSION_24BIT );
251 if( !rBmpEx.IsTransparent() )
252 rReturn = aBmp;
253 else
255 aVDev.DrawBitmap( aNullPt, aVDev.GetOutputSizePixel(), rBmpEx.GetMask() );
256 Bitmap aOverlayMergeBmp( aVDev.GetBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize() ) );
258 if( rOverlay.IsTransparent() )
259 aVDev.DrawBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), rOverlay.GetMask() );
260 else
262 aVDev.SetLineColor( COL_BLACK );
263 aVDev.SetFillColor( COL_BLACK );
264 aVDev.DrawRect( aOverlayRect);
267 aOverlayMergeBmp.CombineSimple( aVDev.GetBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize() ), BMP_COMBINE_AND );
268 aVDev.DrawBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), aOverlayMergeBmp );
269 rReturn = BitmapEx( aBmp, aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() ) );
274 return !rReturn.IsEmpty();
278 //---------------------------------------------------------------
279 // static
280 sal_Bool GraphicHelper::createThumb_Impl( const GDIMetaFile& rMtf,
281 sal_uInt32 nMaximumExtent,
282 BitmapEx& rBmpEx,
283 const BitmapEx* pOverlay,
284 const Rectangle* pOverlayRect )
286 // the implementation is provided by KA
288 // initialization seems to be complicated but is used to avoid rounding errors
289 VirtualDevice aVDev;
290 const Point aNullPt;
291 const Point aTLPix( aVDev.LogicToPixel( aNullPt, rMtf.GetPrefMapMode() ) );
292 const Point aBRPix( aVDev.LogicToPixel( Point( rMtf.GetPrefSize().Width() - 1, rMtf.GetPrefSize().Height() - 1 ), rMtf.GetPrefMapMode() ) );
293 Size aDrawSize( aVDev.LogicToPixel( rMtf.GetPrefSize(), rMtf.GetPrefMapMode() ) );
294 Size aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 );
296 if ( !rBmpEx.IsEmpty() )
297 rBmpEx.SetEmpty();
299 // determine size that has the same aspect ratio as image size and
300 // fits into the rectangle determined by nMaximumExtent
301 if ( aSizePix.Width() && aSizePix.Height() &&
302 ( sal::static_int_cast<sal_uInt32>(aSizePix.Width()) > nMaximumExtent ||
303 sal::static_int_cast<sal_uInt32>(aSizePix.Height()) > nMaximumExtent ) )
305 const Size aOldSizePix( aSizePix );
306 double fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height();
308 if ( fWH <= 1.0 )
310 aSizePix.Width() = FRound( nMaximumExtent * fWH );
311 aSizePix.Height() = nMaximumExtent;
313 else
315 aSizePix.Width() = nMaximumExtent;
316 aSizePix.Height() = FRound( nMaximumExtent / fWH );
319 aDrawSize.Width() = FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() );
320 aDrawSize.Height() = FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() );
323 Size aFullSize;
324 Point aBackPosPix;
325 Rectangle aOverlayRect;
327 // calculate addigtional positions and sizes if an overlay image is used
328 if ( pOverlay )
330 aFullSize = Size( nMaximumExtent, nMaximumExtent );
331 aOverlayRect = Rectangle( aNullPt, aFullSize );
333 aOverlayRect.Intersection( pOverlayRect ? *pOverlayRect : Rectangle( aNullPt, pOverlay->GetSizePixel() ) );
335 if ( !aOverlayRect.IsEmpty() )
336 aBackPosPix = Point( ( nMaximumExtent - aSizePix.Width() ) >> 1, ( nMaximumExtent - aSizePix.Height() ) >> 1 );
337 else
338 pOverlay = NULL;
340 else
342 aFullSize = aSizePix;
343 pOverlay = NULL;
346 // draw image(s) into VDev and get resulting image
347 if ( aVDev.SetOutputSizePixel( aFullSize ) )
349 // draw metafile into VDev
350 const_cast< GDIMetaFile& >( rMtf ).WindStart();
351 const_cast< GDIMetaFile& >( rMtf ).Play( &aVDev, aBackPosPix, aDrawSize );
353 // draw overlay if necessary
354 if ( pOverlay )
355 aVDev.DrawBitmapEx( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), *pOverlay );
357 // get paint bitmap
358 Bitmap aBmp( aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() ) );
360 // assure that we have a true color image
361 if ( aBmp.GetBitCount() != 24 )
362 aBmp.Convert( BMP_CONVERSION_24BIT );
364 rBmpEx = BitmapEx( aBmp );
367 return !rBmpEx.IsEmpty();
370 //---------------------------------------------------------------
371 // static
372 sal_Bool GraphicHelper::getThumbnailFormatFromGDI_Impl( GDIMetaFile* pMetaFile,
373 sal_Bool bSigned,
374 const uno::Reference< io::XStream >& xStream )
376 sal_Bool bResult = sal_False;
377 SvStream* pStream = NULL;
379 if ( xStream.is() )
380 pStream = ::utl::UcbStreamHelper::CreateStream( xStream );
382 if ( pMetaFile && pStream && !pStream->GetError() )
384 BitmapEx aResultBitmap;
385 BitmapEx* pSignatureBitmap = NULL;
387 if ( bSigned )
388 pSignatureBitmap = new BitmapEx( SfxResId( BMP_SIGNATURE ) );
390 bResult = createThumb_Impl( *pMetaFile,
391 THUMBNAIL_RESOLUTION,
392 aResultBitmap,
393 pSignatureBitmap );
394 if ( bResult )
395 bResult = ( !aResultBitmap.IsEmpty()
396 && GraphicConverter::Export( *pStream, aResultBitmap, CVT_PNG ) == 0
397 && ( pStream->Flush(), !pStream->GetError() ) );
399 if ( pSignatureBitmap )
400 delete pSignatureBitmap;
402 delete pStream;
405 return bResult;
408 //---------------------------------------------------------------
409 // static
410 sal_Bool GraphicHelper::getSignedThumbnailFormatFromBitmap_Impl( const BitmapEx& aBitmap,
411 const uno::Reference< io::XStream >& xStream )
413 sal_Bool bResult = sal_False;
414 SvStream* pStream = NULL;
416 if ( xStream.is() )
417 pStream = ::utl::UcbStreamHelper::CreateStream( xStream );
419 if ( pStream && !pStream->GetError() )
421 BitmapEx aResultBitmap;
422 BitmapEx aSignatureBitmap( SfxResId( BMP_SIGNATURE ) );
424 bResult = mergeBitmaps_Impl( aBitmap,
425 aSignatureBitmap,
426 Rectangle( Point(), aBitmap.GetSizePixel() ),
427 aResultBitmap );
429 if ( bResult )
431 bResult = ( !aResultBitmap.IsEmpty()
432 && GraphicConverter::Export( *pStream, aResultBitmap, CVT_PNG ) == 0
433 && ( pStream->Flush(), !pStream->GetError() ) );
436 delete pStream;
439 return bResult;
442 //---------------------------------------------------------------
443 // static
444 sal_Bool GraphicHelper::getThumbnailReplacement_Impl( sal_Int32 nResID, const uno::Reference< io::XStream >& xStream )
446 sal_Bool bResult = sal_False;
447 if ( nResID && xStream.is() )
449 uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
452 uno::Reference< graphic::XGraphicProvider > xGraphProvider(graphic::GraphicProvider::create(xContext));
453 OUString aURL("private:resource/sfx/bitmapex/");
454 aURL += OUString::valueOf( nResID );
456 uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
457 aMediaProps[0].Name = "URL";
458 aMediaProps[0].Value <<= aURL;
460 uno::Reference< graphic::XGraphic > xGraphic = xGraphProvider->queryGraphic( aMediaProps );
461 if ( xGraphic.is() )
463 uno::Sequence< beans::PropertyValue > aStoreProps( 2 );
464 aStoreProps[0].Name = "OutputStream";
465 aStoreProps[0].Value <<= xStream;
466 aStoreProps[1].Name = "MimeType";
467 aStoreProps[1].Value <<= OUString("image/png");
469 xGraphProvider->storeGraphic( xGraphic, aStoreProps );
470 bResult = sal_True;
473 catch(const uno::Exception&)
478 return bResult;
481 //---------------------------------------------------------------
482 // static
483 sal_uInt16 GraphicHelper::getThumbnailReplacementIDByFactoryName_Impl( const OUString& aFactoryShortName, sal_Bool /*bIsTemplate*/ )
485 sal_uInt16 nResult = 0;
487 if ( aFactoryShortName == "scalc" )
489 nResult = BMP_128X128_CALC_DOC;
491 else if ( aFactoryShortName == "sdraw" )
493 nResult = BMP_128X128_DRAW_DOC;
495 else if ( aFactoryShortName == "simpress" )
497 nResult = BMP_128X128_IMPRESS_DOC;
499 else if ( aFactoryShortName == "smath" )
501 nResult = BMP_128X128_MATH_DOC;
503 else if ( aFactoryShortName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "swriter" ) ) || aFactoryShortName.startsWith("swriter/") )
505 nResult = BMP_128X128_WRITER_DOC;
508 return nResult;
511 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */