update emoji autocorrect entries from po-files
[LibreOffice.git] / vcl / source / gdi / gdimtf.cxx
blob8d283dff051a92ca916eb1a3bfc8a0491527b281
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 .
20 #include <rtl/crc.h>
21 #include <tools/stream.hxx>
22 #include <tools/vcompat.hxx>
23 #include <tools/fract.hxx>
24 #include <vcl/metaact.hxx>
25 #include <vcl/salbtype.hxx>
26 #include <vcl/outdev.hxx>
27 #include <vcl/window.hxx>
28 #include <vcl/virdev.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/gdimtf.hxx>
31 #include <vcl/graphictools.hxx>
32 #include <basegfx/polygon/b2dpolygon.hxx>
33 #include <vcl/canvastools.hxx>
35 #include <cvtsvm.hxx>
36 #include <salbmp.hxx>
37 #include <salinst.hxx>
38 #include <svdata.hxx>
40 #include <com/sun/star/beans/XFastPropertySet.hpp>
41 #include <com/sun/star/rendering/MtfRenderer.hpp>
42 #include <com/sun/star/rendering/XBitmapCanvas.hpp>
43 #include <com/sun/star/rendering/XCanvas.hpp>
44 #include <comphelper/processfactory.hxx>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <com/sun/star/lang/XInitialization.hpp>
47 #include <com/sun/star/awt/XGraphics.hpp>
48 #include <com/sun/star/graphic/XGraphic.hpp>
49 #include <com/sun/star/graphic/XGraphicRenderer.hpp>
51 using namespace com::sun::star;
53 #define GAMMA( _def_cVal, _def_InvGamma ) ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
55 struct ImplColAdjustParam
57 sal_uInt8* pMapR;
58 sal_uInt8* pMapG;
59 sal_uInt8* pMapB;
62 struct ImplBmpAdjustParam
64 short nLuminancePercent;
65 short nContrastPercent;
66 short nChannelRPercent;
67 short nChannelGPercent;
68 short nChannelBPercent;
69 double fGamma;
70 bool bInvert;
73 struct ImplColConvertParam
75 MtfConversion eConversion;
78 struct ImplBmpConvertParam
80 BmpConversion eConversion;
83 struct ImplColMonoParam
85 Color aColor;
88 struct ImplBmpMonoParam
90 Color aColor;
93 struct ImplColReplaceParam
95 sal_uLong* pMinR;
96 sal_uLong* pMaxR;
97 sal_uLong* pMinG;
98 sal_uLong* pMaxG;
99 sal_uLong* pMinB;
100 sal_uLong* pMaxB;
101 const Color* pDstCols;
102 sal_uLong nCount;
105 struct ImplBmpReplaceParam
107 const Color* pSrcCols;
108 const Color* pDstCols;
109 sal_uLong nCount;
110 const sal_uLong* pTols;
113 GDIMetaFile::GDIMetaFile() :
114 nCurrentActionElement( 0 ),
115 aPrefSize ( 1, 1 ),
116 pPrev ( NULL ),
117 pNext ( NULL ),
118 pOutDev ( NULL ),
119 bPause ( false ),
120 bRecord ( false ),
121 bUseCanvas ( false )
125 GDIMetaFile::GDIMetaFile( const GDIMetaFile& rMtf ) :
126 nCurrentActionElement( rMtf.nCurrentActionElement ),
127 aPrefMapMode ( rMtf.aPrefMapMode ),
128 aPrefSize ( rMtf.aPrefSize ),
129 aHookHdlLink ( rMtf.aHookHdlLink ),
130 pPrev ( rMtf.pPrev ),
131 pNext ( rMtf.pNext ),
132 pOutDev ( NULL ),
133 bPause ( false ),
134 bRecord ( false ),
135 bUseCanvas ( rMtf.bUseCanvas )
137 // Increment RefCount of MetaActions
138 for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
140 rMtf.GetAction( i )->Duplicate();
141 aList.push_back( rMtf.GetAction( i ) );
144 if( rMtf.bRecord )
146 Record( rMtf.pOutDev );
148 if ( rMtf.bPause )
149 Pause( true );
153 GDIMetaFile::~GDIMetaFile()
155 Clear();
158 size_t GDIMetaFile::GetActionSize() const
160 return aList.size();
163 MetaAction* GDIMetaFile::GetAction( size_t nAction ) const
165 return (nAction < aList.size()) ? aList[ nAction ] : NULL;
168 MetaAction* GDIMetaFile::FirstAction()
170 nCurrentActionElement = 0;
171 return aList.empty() ? NULL : aList[ 0 ];
174 MetaAction* GDIMetaFile::NextAction()
176 return ( nCurrentActionElement + 1 < aList.size() ) ? aList[ ++nCurrentActionElement ] : NULL;
179 MetaAction* GDIMetaFile::ReplaceAction( MetaAction* pAction, size_t nAction )
181 if ( nAction >= aList.size() )
183 // this method takes ownership of pAction and is
184 // therefore responsible for deleting it
185 pAction->Delete();
186 return NULL;
188 //fdo#39995 This does't increment the incoming action ref-count nor does it
189 //decrement the outgoing action ref-count
190 std::swap(pAction, aList[nAction]);
191 return pAction;
194 GDIMetaFile& GDIMetaFile::operator=( const GDIMetaFile& rMtf )
196 if( this != &rMtf )
198 Clear();
200 // Increment RefCount of MetaActions
201 for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
203 rMtf.GetAction( i )->Duplicate();
204 aList.push_back( rMtf.GetAction( i ) );
207 aPrefMapMode = rMtf.aPrefMapMode;
208 aPrefSize = rMtf.aPrefSize;
209 aHookHdlLink = rMtf.aHookHdlLink;
210 pPrev = rMtf.pPrev;
211 pNext = rMtf.pNext;
212 pOutDev = NULL;
213 bPause = false;
214 bRecord = false;
215 bUseCanvas = rMtf.bUseCanvas;
217 if( rMtf.bRecord )
219 Record( rMtf.pOutDev );
221 if( rMtf.bPause )
222 Pause( true );
226 return *this;
229 bool GDIMetaFile::operator==( const GDIMetaFile& rMtf ) const
231 const size_t nObjCount = aList.size();
232 bool bRet = false;
234 if( this == &rMtf )
235 bRet = true;
236 else if( rMtf.GetActionSize() == nObjCount &&
237 rMtf.GetPrefSize() == aPrefSize &&
238 rMtf.GetPrefMapMode() == aPrefMapMode )
240 bRet = true;
242 for( size_t n = 0; n < nObjCount; n++ )
244 if( aList[ n ] != rMtf.GetAction( n ) )
246 bRet = false;
247 break;
252 return bRet;
255 void GDIMetaFile::Clear()
257 if( bRecord )
258 Stop();
260 for( size_t i = 0, n = aList.size(); i < n; ++i )
261 aList[ i ]->Delete();
262 aList.clear();
265 void GDIMetaFile::Linker( OutputDevice* pOut, bool bLink )
267 if( bLink )
269 pNext = NULL;
270 pPrev = pOut->GetConnectMetaFile();
271 pOut->SetConnectMetaFile( this );
273 if( pPrev )
274 pPrev->pNext = this;
276 else
278 if( pNext )
280 pNext->pPrev = pPrev;
282 if( pPrev )
283 pPrev->pNext = pNext;
285 else
287 if( pPrev )
288 pPrev->pNext = NULL;
290 pOut->SetConnectMetaFile( pPrev );
293 pPrev = NULL;
294 pNext = NULL;
298 long GDIMetaFile::Hook()
300 return aHookHdlLink.Call( this );
303 void GDIMetaFile::Record( OutputDevice* pOut )
305 if( bRecord )
306 Stop();
308 nCurrentActionElement = aList.empty() ? 0 : (aList.size() - 1);
309 pOutDev = pOut;
310 bRecord = true;
311 Linker( pOut, true );
314 void GDIMetaFile::Play( GDIMetaFile& rMtf, size_t nPos )
316 if ( !bRecord && !rMtf.bRecord )
318 MetaAction* pAction = GetCurAction();
319 const size_t nObjCount = aList.size();
321 rMtf.UseCanvas( rMtf.GetUseCanvas() || bUseCanvas );
323 if( nPos > nObjCount )
324 nPos = nObjCount;
326 for( size_t nCurPos = nCurrentActionElement; nCurPos < nPos; nCurPos++ )
328 if( !Hook() && pAction )
330 pAction->Duplicate();
331 rMtf.AddAction( pAction );
334 pAction = NextAction();
339 void GDIMetaFile::Play( OutputDevice* pOut, size_t nPos )
341 if( !bRecord )
343 MetaAction* pAction = GetCurAction();
344 const size_t nObjCount = aList.size();
345 size_t nSyncCount = ( pOut->GetOutDevType() == OUTDEV_WINDOW ) ? 0x000000ff : 0xffffffff;
347 if( nPos > nObjCount )
348 nPos = nObjCount;
350 // #i23407# Set backwards-compatible text language and layout mode
351 // This is necessary, since old metafiles don't even know of these
352 // recent add-ons. Newer metafiles must of course explicitly set
353 // those states.
354 pOut->Push( PushFlags::TEXTLAYOUTMODE|PushFlags::TEXTLANGUAGE );
355 pOut->SetLayoutMode( TEXT_LAYOUT_DEFAULT );
356 pOut->SetDigitLanguage( 0 );
358 OSL_TRACE("GDIMetaFile::Play on device of size: %ld x %ld", pOut->GetOutputSizePixel().Width(), pOut->GetOutputSizePixel().Height());
360 if( !ImplPlayWithRenderer( pOut, Point(0,0), pOut->GetOutputSize() ) ) {
361 size_t i = 0;
362 for( size_t nCurPos = nCurrentActionElement; nCurPos < nPos; nCurPos++ )
364 if( !Hook() && pAction )
366 if( pAction->GetType() == MetaActionType::COMMENT &&
367 static_cast<MetaCommentAction*>(pAction)->GetComment() == "DELEGATE_PLUGGABLE_RENDERER" )
369 ImplDelegate2PluggableRenderer(static_cast<MetaCommentAction*>(pAction), pOut);
371 else
373 pAction->Execute( pOut );
376 // flush output from time to time
377 if( i++ > nSyncCount )
379 static_cast<vcl::Window*>( pOut )->Flush();
380 i = 0;
384 pAction = NextAction();
387 pOut->Pop();
391 bool GDIMetaFile::ImplPlayWithRenderer( OutputDevice* pOut, const Point& rPos, Size rLogicDestSize )
393 if (!bUseCanvas)
394 return false;
396 Size rDestSize( pOut->LogicToPixel( rLogicDestSize ) );
398 const vcl::Window* win = dynamic_cast <vcl::Window*> ( pOut );
400 if (!win)
401 win = Application::GetActiveTopWindow();
402 if (!win)
403 win = Application::GetFirstTopLevelWindow();
405 if (!win)
406 return false;
410 uno::Reference<rendering::XCanvas> xCanvas = win->GetCanvas ();
412 if (!xCanvas.is())
413 return false;
415 Size aSize (rDestSize.Width () + 1, rDestSize.Height () + 1);
416 uno::Reference<rendering::XBitmap> xBitmap = xCanvas->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize));
417 if( xBitmap.is () )
419 uno::Reference< rendering::XBitmapCanvas > xBitmapCanvas( xBitmap, uno::UNO_QUERY );
420 if( xBitmapCanvas.is() )
422 uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
423 uno::Reference< rendering::XMtfRenderer > xMtfRenderer = rendering::MtfRenderer::createWithBitmapCanvas( xContext, xBitmapCanvas );
425 xBitmapCanvas->clear();
426 uno::Reference< beans::XFastPropertySet > xMtfFastPropertySet( xMtfRenderer, uno::UNO_QUERY );
427 if( xMtfFastPropertySet.is() )
428 // set this metafile to the renderer to
429 // speedup things (instead of copying data to
430 // sequence of bytes passed to renderer)
431 xMtfFastPropertySet->setFastPropertyValue( 0, uno::Any( reinterpret_cast<sal_Int64>( this ) ) );
433 xMtfRenderer->draw( rDestSize.Width(), rDestSize.Height() );
435 BitmapEx aBitmapEx;
436 if( aBitmapEx.Create( xBitmapCanvas, aSize ) )
438 if ( pOut->GetMapMode() == MAP_PIXEL )
439 pOut->DrawBitmapEx( rPos, aBitmapEx );
440 else
441 pOut->DrawBitmapEx( rPos, rLogicDestSize, aBitmapEx );
442 return true;
447 catch (const uno::RuntimeException& )
449 throw; // runtime errors are fatal
451 catch (const uno::Exception& e)
453 // ignore errors, no way of reporting them here
454 SAL_WARN("vcl",
455 "GDIMetaFile::ImplPlayWithRenderer: exception: " << e.Message);
458 return false;
461 void GDIMetaFile::ImplDelegate2PluggableRenderer( const MetaCommentAction* pAct, OutputDevice* pOut )
463 OSL_ASSERT( pAct->GetComment() == "DELEGATE_PLUGGABLE_RENDERER" );
465 // read payload - string of service name, followed by raw render input
466 const sal_uInt8* pData = pAct->GetData();
467 const sal_uInt8* const pEndData = pData + pAct->GetDataSize();
468 if( !pData )
469 return;
471 OUStringBuffer aBuffer;
472 while( pData<pEndData && *pData )
473 aBuffer.append(static_cast<sal_Unicode>(*pData++));
474 const OUString aRendererServiceName=aBuffer.makeStringAndClear();
475 ++pData;
477 while( pData<pEndData && *pData )
478 aBuffer.append(static_cast<sal_Unicode>(*pData++));
479 const OUString aGraphicServiceName=aBuffer.makeStringAndClear();
480 ++pData;
482 uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
483 if( pData<pEndData )
487 // instantiate render service
488 uno::Sequence<uno::Any> aRendererArgs(1);
489 aRendererArgs[0] = makeAny(uno::Reference<awt::XGraphics>(pOut->CreateUnoGraphics()));
490 uno::Reference<graphic::XGraphicRenderer> xRenderer(
491 xFactory->createInstanceWithArguments(
492 aRendererServiceName,
493 aRendererArgs),
494 uno::UNO_QUERY );
496 // instantiate graphic service
497 uno::Reference<graphic::XGraphic> xGraphic(
498 xFactory->createInstance(
499 aGraphicServiceName),
500 uno::UNO_QUERY );
502 uno::Reference<lang::XInitialization> xInit(
503 xGraphic, uno::UNO_QUERY);
505 if(xGraphic.is() && xRenderer.is() && xInit.is())
507 // delay intialization of XGraphic, to only expose
508 // XGraphic-generating services to arbitrary binary data
509 uno::Sequence< sal_Int8 > aSeq(
510 reinterpret_cast<sal_Int8 const *>(pData), pEndData-pData );
511 uno::Sequence<uno::Any> aGraphicsArgs(1);
512 aGraphicsArgs[0] = makeAny(aSeq);
513 xInit->initialize(aGraphicsArgs);
515 xRenderer->render(xGraphic);
518 catch (const uno::RuntimeException&)
520 // runtime errors are fatal
521 throw;
523 catch (const uno::Exception& e)
525 // ignore errors, no way of reporting them here
526 SAL_WARN("vcl", "GDIMetaFile::ImplDelegate2PluggableRenderer:"
527 " exception: " << e.Message);
532 void GDIMetaFile::Play( OutputDevice* pOut, const Point& rPos,
533 const Size& rSize, size_t nPos )
535 vcl::Region aDrawClipRegion;
536 MapMode aDrawMap( GetPrefMapMode() );
537 Size aDestSize( pOut->LogicToPixel( rSize ) );
539 if( aDestSize.Width() && aDestSize.Height() )
541 GDIMetaFile* pMtf = pOut->GetConnectMetaFile();
543 if( ImplPlayWithRenderer( pOut, rPos, rSize ) )
544 return;
546 Size aTmpPrefSize( pOut->LogicToPixel( GetPrefSize(), aDrawMap ) );
548 if( !aTmpPrefSize.Width() )
549 aTmpPrefSize.Width() = aDestSize.Width();
551 if( !aTmpPrefSize.Height() )
552 aTmpPrefSize.Height() = aDestSize.Height();
554 Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() );
555 Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() );
557 aScaleX *= aDrawMap.GetScaleX(); aDrawMap.SetScaleX( aScaleX );
558 aScaleY *= aDrawMap.GetScaleY(); aDrawMap.SetScaleY( aScaleY );
560 // #i47260# Convert logical output position to offset within
561 // the metafile's mapmode. Therefore, disable pixel offset on
562 // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
563 // different mapmode (the one currently set on pOut, that is)
564 // - thus, aDrawMap's origin would generally be wrong. And
565 // even _if_ aDrawMap is similar to pOutDev's current mapmode,
566 // it's _still_ undesirable to have pixel offset unequal zero,
567 // because one would still get round-off errors (the
568 // round-trip error for LogicToPixel( PixelToLogic() ) was the
569 // reason for having pixel offset in the first place).
570 const Size& rOldOffset( pOut->GetPixelOffset() );
571 const Size aEmptySize;
572 pOut->SetPixelOffset( aEmptySize );
573 aDrawMap.SetOrigin( pOut->PixelToLogic( pOut->LogicToPixel( rPos ), aDrawMap ) );
574 pOut->SetPixelOffset( rOldOffset );
576 pOut->Push();
578 if ( pMtf && pMtf->IsRecord() && ( pOut->GetOutDevType() != OUTDEV_PRINTER ) )
579 pOut->SetRelativeMapMode( aDrawMap );
580 else
581 pOut->SetMapMode( aDrawMap );
583 // #i23407# Set backwards-compatible text language and layout mode
584 // This is necessary, since old metafiles don't even know of these
585 // recent add-ons. Newer metafiles must of course explicitly set
586 // those states.
587 pOut->SetLayoutMode( TEXT_LAYOUT_DEFAULT );
588 pOut->SetDigitLanguage( 0 );
590 Play( pOut, nPos );
592 pOut->Pop();
596 void GDIMetaFile::Pause( bool _bPause )
598 if( bRecord )
600 if( _bPause )
602 if( !bPause )
603 Linker( pOutDev, false );
605 else
607 if( bPause )
608 Linker( pOutDev, true );
611 bPause = _bPause;
615 void GDIMetaFile::Stop()
617 if( bRecord )
619 bRecord = false;
621 if( !bPause )
622 Linker( pOutDev, false );
623 else
624 bPause = false;
628 void GDIMetaFile::WindStart()
630 if( !bRecord )
631 nCurrentActionElement = 0;
634 void GDIMetaFile::WindPrev()
636 if( !bRecord )
637 if ( nCurrentActionElement > 0 )
638 --nCurrentActionElement;
641 void GDIMetaFile::AddAction( MetaAction* pAction )
643 aList.push_back( pAction );
645 if( pPrev )
647 pAction->Duplicate();
648 pPrev->AddAction( pAction );
652 void GDIMetaFile::AddAction( MetaAction* pAction, size_t nPos )
654 if ( nPos < aList.size() )
656 ::std::vector< MetaAction* >::iterator it = aList.begin();
657 ::std::advance( it, nPos );
658 aList.insert( it, pAction );
660 else
662 aList.push_back( pAction );
665 if( pPrev )
667 pAction->Duplicate();
668 pPrev->AddAction( pAction, nPos );
672 void GDIMetaFile::push_back( MetaAction* pAction )
674 aList.push_back( pAction );
677 void GDIMetaFile::RemoveAction( size_t nPos )
679 if ( nPos < aList.size() )
681 ::std::vector< MetaAction* >::iterator it = aList.begin();
682 ::std::advance( it, nPos );
683 (*it)->Delete();
684 aList.erase( it );
688 if( pPrev )
689 pPrev->RemoveAction( nPos );
692 bool GDIMetaFile::Mirror( BmpMirrorFlags nMirrorFlags )
694 const Size aOldPrefSize( GetPrefSize() );
695 long nMoveX, nMoveY;
696 double fScaleX, fScaleY;
697 bool bRet;
699 if( nMirrorFlags & BmpMirrorFlags::Horizontal )
700 nMoveX = SAL_ABS( aOldPrefSize.Width() ) - 1, fScaleX = -1.0;
701 else
702 nMoveX = 0, fScaleX = 1.0;
704 if( nMirrorFlags & BmpMirrorFlags::Vertical )
705 nMoveY = SAL_ABS( aOldPrefSize.Height() ) - 1, fScaleY = -1.0;
706 else
707 nMoveY = 0, fScaleY = 1.0;
709 if( ( fScaleX != 1.0 ) || ( fScaleY != 1.0 ) )
711 Scale( fScaleX, fScaleY );
712 Move( nMoveX, nMoveY );
713 SetPrefSize( aOldPrefSize );
714 bRet = true;
716 else
717 bRet = false;
719 return bRet;
722 void GDIMetaFile::Move( long nX, long nY )
724 const Size aBaseOffset( nX, nY );
725 Size aOffset( aBaseOffset );
726 ScopedVclPtrInstance< VirtualDevice > aMapVDev;
728 aMapVDev->EnableOutput( false );
729 aMapVDev->SetMapMode( GetPrefMapMode() );
731 for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
733 const MetaActionType nType = pAct->GetType();
734 MetaAction* pModAct;
736 if( pAct->GetRefCount() > 1 )
738 aList[ nCurrentActionElement ] = pModAct = pAct->Clone();
739 pAct->Delete();
741 else
742 pModAct = pAct;
744 if( ( MetaActionType::MAPMODE == nType ) ||
745 ( MetaActionType::PUSH == nType ) ||
746 ( MetaActionType::POP == nType ) )
748 pModAct->Execute( aMapVDev.get() );
749 aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
752 pModAct->Move( aOffset.Width(), aOffset.Height() );
756 void GDIMetaFile::Move( long nX, long nY, long nDPIX, long nDPIY )
758 const Size aBaseOffset( nX, nY );
759 Size aOffset( aBaseOffset );
760 ScopedVclPtrInstance< VirtualDevice > aMapVDev;
762 aMapVDev->EnableOutput( false );
763 aMapVDev->SetReferenceDevice( nDPIX, nDPIY );
764 aMapVDev->SetMapMode( GetPrefMapMode() );
766 for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
768 const MetaActionType nType = pAct->GetType();
769 MetaAction* pModAct;
771 if( pAct->GetRefCount() > 1 )
773 aList[ nCurrentActionElement ] = pModAct = pAct->Clone();
774 pAct->Delete();
776 else
777 pModAct = pAct;
779 if( ( MetaActionType::MAPMODE == nType ) ||
780 ( MetaActionType::PUSH == nType ) ||
781 ( MetaActionType::POP == nType ) )
783 pModAct->Execute( aMapVDev.get() );
784 if( aMapVDev->GetMapMode().GetMapUnit() == MAP_PIXEL )
786 aOffset = aMapVDev->LogicToPixel( aBaseOffset, GetPrefMapMode() );
787 MapMode aMap( aMapVDev->GetMapMode() );
788 aOffset.Width() = static_cast<long>(aOffset.Width() * (double)aMap.GetScaleX());
789 aOffset.Height() = static_cast<long>(aOffset.Height() * (double)aMap.GetScaleY());
791 else
792 aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
795 pModAct->Move( aOffset.Width(), aOffset.Height() );
799 void GDIMetaFile::Scale( double fScaleX, double fScaleY )
801 for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
803 MetaAction* pModAct;
805 if( pAct->GetRefCount() > 1 )
807 aList[ nCurrentActionElement ] = pModAct = pAct->Clone();
808 pAct->Delete();
810 else
811 pModAct = pAct;
813 pModAct->Scale( fScaleX, fScaleY );
816 aPrefSize.Width() = FRound( aPrefSize.Width() * fScaleX );
817 aPrefSize.Height() = FRound( aPrefSize.Height() * fScaleY );
820 void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY )
822 Scale( (double) rScaleX, (double) rScaleY );
825 void GDIMetaFile::Clip( const Rectangle& i_rClipRect )
827 Rectangle aCurRect( i_rClipRect );
828 ScopedVclPtrInstance< VirtualDevice > aMapVDev;
830 aMapVDev->EnableOutput( false );
831 aMapVDev->SetMapMode( GetPrefMapMode() );
833 for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
835 const MetaActionType nType = pAct->GetType();
837 if( ( MetaActionType::MAPMODE == nType ) ||
838 ( MetaActionType::PUSH == nType ) ||
839 ( MetaActionType::POP == nType ) )
841 pAct->Execute( aMapVDev.get() );
842 aCurRect = OutputDevice::LogicToLogic( i_rClipRect, GetPrefMapMode(), aMapVDev->GetMapMode() );
844 else if( nType == MetaActionType::CLIPREGION )
846 MetaClipRegionAction* pOldAct = static_cast<MetaClipRegionAction*>(pAct);
847 vcl::Region aNewReg( aCurRect );
848 if( pOldAct->IsClipping() )
849 aNewReg.Intersect( pOldAct->GetRegion() );
850 MetaClipRegionAction* pNewAct = new MetaClipRegionAction( aNewReg, true );
851 aList[ nCurrentActionElement ] = pNewAct;
852 pOldAct->Delete();
857 Point GDIMetaFile::ImplGetRotatedPoint( const Point& rPt, const Point& rRotatePt,
858 const Size& rOffset, double fSin, double fCos )
860 const long nX = rPt.X() - rRotatePt.X();
861 const long nY = rPt.Y() - rRotatePt.Y();
863 return Point( FRound( fCos * nX + fSin * nY ) + rRotatePt.X() + rOffset.Width(),
864 -FRound( fSin * nX - fCos * nY ) + rRotatePt.Y() + rOffset.Height() );
867 Polygon GDIMetaFile::ImplGetRotatedPolygon( const Polygon& rPoly, const Point& rRotatePt,
868 const Size& rOffset, double fSin, double fCos )
870 Polygon aRet( rPoly );
872 aRet.Rotate( rRotatePt, fSin, fCos );
873 aRet.Move( rOffset.Width(), rOffset.Height() );
875 return aRet;
878 tools::PolyPolygon GDIMetaFile::ImplGetRotatedPolyPolygon( const tools::PolyPolygon& rPolyPoly, const Point& rRotatePt,
879 const Size& rOffset, double fSin, double fCos )
881 tools::PolyPolygon aRet( rPolyPoly );
883 aRet.Rotate( rRotatePt, fSin, fCos );
884 aRet.Move( rOffset.Width(), rOffset.Height() );
886 return aRet;
889 void GDIMetaFile::ImplAddGradientEx( GDIMetaFile& rMtf,
890 const OutputDevice& rMapDev,
891 const tools::PolyPolygon& rPolyPoly,
892 const Gradient& rGrad )
894 // Generate comment, GradientEx and Gradient actions (within DrawGradient)
895 ScopedVclPtrInstance< VirtualDevice > aVDev( rMapDev, 0 );
896 aVDev->EnableOutput( false );
897 GDIMetaFile aGradMtf;
899 aGradMtf.Record( aVDev.get() );
900 aVDev->DrawGradient( rPolyPoly, rGrad );
901 aGradMtf.Stop();
903 size_t i, nAct( aGradMtf.GetActionSize() );
904 for( i=0; i < nAct; ++i )
906 MetaAction* pMetaAct = aGradMtf.GetAction( i );
907 pMetaAct->Duplicate();
908 rMtf.AddAction( pMetaAct );
912 void GDIMetaFile::Rotate( long nAngle10 )
914 nAngle10 %= 3600L;
915 nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
917 if( nAngle10 )
919 GDIMetaFile aMtf;
920 ScopedVclPtrInstance< VirtualDevice > aMapVDev;
921 const double fAngle = F_PI1800 * nAngle10;
922 const double fSin = sin( fAngle );
923 const double fCos = cos( fAngle );
924 Rectangle aRect=Rectangle( Point(), GetPrefSize() );
925 Polygon aPoly( aRect );
927 aPoly.Rotate( Point(), fSin, fCos );
929 aMapVDev->EnableOutput( false );
930 aMapVDev->SetMapMode( GetPrefMapMode() );
932 const Rectangle aNewBound( aPoly.GetBoundRect() );
934 const Point aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
935 const Size aOffset( -aNewBound.Left(), -aNewBound.Top() );
937 Point aRotAnchor( aOrigin );
938 Size aRotOffset( aOffset );
940 for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
942 const MetaActionType nActionType = pAction->GetType();
944 switch( nActionType )
946 case( MetaActionType::PIXEL ):
948 MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
949 aMtf.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
950 pAct->GetColor() ) );
952 break;
954 case( MetaActionType::POINT ):
956 MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
957 aMtf.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
959 break;
961 case( MetaActionType::LINE ):
963 MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
964 aMtf.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
965 ImplGetRotatedPoint( pAct->GetEndPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
966 pAct->GetLineInfo() ) );
968 break;
970 case( MetaActionType::RECT ):
972 MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
973 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
975 break;
977 case( MetaActionType::ROUNDRECT ):
979 MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
980 const Polygon aRoundRectPoly( pAct->GetRect(), pAct->GetHorzRound(), pAct->GetVertRound() );
982 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
984 break;
986 case( MetaActionType::ELLIPSE ):
988 MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
989 const Polygon aEllipsePoly( pAct->GetRect().Center(), pAct->GetRect().GetWidth() >> 1, pAct->GetRect().GetHeight() >> 1 );
991 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
993 break;
995 case( MetaActionType::ARC ):
997 MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
998 const Polygon aArcPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_ARC );
1000 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1002 break;
1004 case( MetaActionType::PIE ):
1006 MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
1007 const Polygon aPiePoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_PIE );
1009 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1011 break;
1013 case( MetaActionType::CHORD ):
1015 MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
1016 const Polygon aChordPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_CHORD );
1018 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1020 break;
1022 case( MetaActionType::POLYLINE ):
1024 MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
1025 aMtf.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->GetLineInfo() ) );
1027 break;
1029 case( MetaActionType::POLYGON ):
1031 MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
1032 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1034 break;
1036 case( MetaActionType::POLYPOLYGON ):
1038 MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
1039 aMtf.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1041 break;
1043 case( MetaActionType::TEXT ):
1045 MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
1046 aMtf.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1047 pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
1049 break;
1051 case( MetaActionType::TEXTARRAY ):
1053 MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
1054 aMtf.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1055 pAct->GetText(), pAct->GetDXArray(), pAct->GetIndex(), pAct->GetLen() ) );
1057 break;
1059 case( MetaActionType::STRETCHTEXT ):
1061 MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
1062 aMtf.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1063 pAct->GetWidth(), pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
1065 break;
1067 case( MetaActionType::TEXTLINE ):
1069 MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
1070 aMtf.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1071 pAct->GetWidth(), pAct->GetStrikeout(), pAct->GetUnderline(), pAct->GetOverline() ) );
1073 break;
1075 case( MetaActionType::BMPSCALE ):
1077 MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1078 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1079 Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1080 BitmapEx aBmpEx( pAct->GetBitmap() );
1082 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1083 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(),
1084 aBmpEx ) );
1086 break;
1088 case( MetaActionType::BMPSCALEPART ):
1090 MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1091 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1092 Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1093 BitmapEx aBmpEx( pAct->GetBitmap() );
1095 aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1096 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1098 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1100 break;
1102 case( MetaActionType::BMPEXSCALE ):
1104 MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1105 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1106 Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1107 BitmapEx aBmpEx( pAct->GetBitmapEx() );
1109 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1111 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1113 break;
1115 case( MetaActionType::BMPEXSCALEPART ):
1117 MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1118 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1119 Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1120 BitmapEx aBmpEx( pAct->GetBitmapEx() );
1122 aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1123 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1125 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1127 break;
1129 case( MetaActionType::GRADIENT ):
1131 MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1133 ImplAddGradientEx( aMtf, *aMapVDev.get(),
1134 ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ),
1135 pAct->GetGradient() );
1137 break;
1139 case( MetaActionType::GRADIENTEX ):
1141 MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1142 aMtf.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1143 pAct->GetGradient() ) );
1145 break;
1147 // Handle gradientex comment block correctly
1148 case( MetaActionType::COMMENT ):
1150 MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
1151 if( pCommentAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1153 int nBeginComments( 1 );
1154 pAction = NextAction();
1156 // skip everything, except gradientex action
1157 while( pAction )
1159 const MetaActionType nType = pAction->GetType();
1161 if( MetaActionType::GRADIENTEX == nType )
1163 // Add rotated gradientex
1164 MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1165 ImplAddGradientEx( aMtf, *aMapVDev.get(),
1166 ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1167 pAct->GetGradient() );
1169 else if( MetaActionType::COMMENT == nType)
1171 MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pAction);
1172 if( pAct->GetComment() == "XGRAD_SEQ_END" )
1174 // handle nested blocks
1175 --nBeginComments;
1177 // gradientex comment block: end reached, done.
1178 if( !nBeginComments )
1179 break;
1181 else if( pAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1183 // handle nested blocks
1184 ++nBeginComments;
1189 pAction =NextAction();
1192 else
1194 bool bPathStroke = (pCommentAct->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
1195 if ( bPathStroke || pCommentAct->GetComment() == "XPATHFILL_SEQ_BEGIN" )
1197 if ( pCommentAct->GetDataSize() )
1199 SvMemoryStream aMemStm( (void*)pCommentAct->GetData(), pCommentAct->GetDataSize(), StreamMode::READ );
1200 SvMemoryStream aDest;
1201 if ( bPathStroke )
1203 SvtGraphicStroke aStroke;
1204 ReadSvtGraphicStroke( aMemStm, aStroke );
1205 Polygon aPath;
1206 aStroke.getPath( aPath );
1207 aStroke.setPath( ImplGetRotatedPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1208 WriteSvtGraphicStroke( aDest, aStroke );
1209 aMtf.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1210 static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1212 else
1214 SvtGraphicFill aFill;
1215 ReadSvtGraphicFill( aMemStm, aFill );
1216 tools::PolyPolygon aPath;
1217 aFill.getPath( aPath );
1218 aFill.setPath( ImplGetRotatedPolyPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1219 WriteSvtGraphicFill( aDest, aFill );
1220 aMtf.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1221 static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1225 else if ( pCommentAct->GetComment() == "XPATHSTROKE_SEQ_END"
1226 || pCommentAct->GetComment() == "XPATHFILL_SEQ_END" )
1228 pAction->Execute( aMapVDev.get() );
1229 pAction->Duplicate();
1230 aMtf.AddAction( pAction );
1234 break;
1236 case( MetaActionType::HATCH ):
1238 MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1239 Hatch aHatch( pAct->GetHatch() );
1241 aHatch.SetAngle( aHatch.GetAngle() + (sal_uInt16) nAngle10 );
1242 aMtf.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1243 aHatch ) );
1245 break;
1247 case( MetaActionType::Transparent ):
1249 MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1250 aMtf.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1251 pAct->GetTransparence() ) );
1253 break;
1255 case( MetaActionType::FLOATTRANSPARENT ):
1257 MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1258 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
1259 Polygon aMtfPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1260 Rectangle aMtfRect( aMtfPoly.GetBoundRect() );
1262 aTransMtf.Rotate( nAngle10 );
1263 aMtf.AddAction( new MetaFloatTransparentAction( aTransMtf, aMtfRect.TopLeft(), aMtfRect.GetSize(),
1264 pAct->GetGradient() ) );
1266 break;
1268 case( MetaActionType::EPS ):
1270 MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1271 GDIMetaFile aEPSMtf( pAct->GetSubstitute() );
1272 Polygon aEPSPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1273 Rectangle aEPSRect( aEPSPoly.GetBoundRect() );
1275 aEPSMtf.Rotate( nAngle10 );
1276 aMtf.AddAction( new MetaEPSAction( aEPSRect.TopLeft(), aEPSRect.GetSize(),
1277 pAct->GetLink(), aEPSMtf ) );
1279 break;
1281 case( MetaActionType::CLIPREGION ):
1283 MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1285 if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
1286 aMtf.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), true ) );
1287 else
1289 pAction->Duplicate();
1290 aMtf.AddAction( pAction );
1293 break;
1295 case( MetaActionType::ISECTRECTCLIPREGION ):
1297 MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1298 aMtf.AddAction( new MetaISectRegionClipRegionAction(vcl::Region(
1299 ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor,
1300 aRotOffset, fSin, fCos )) ) );
1302 break;
1304 case( MetaActionType::ISECTREGIONCLIPREGION ):
1306 MetaISectRegionClipRegionAction* pAct = static_cast<MetaISectRegionClipRegionAction*>(pAction);
1307 const vcl::Region& rRegion = pAct->GetRegion();
1309 if( rRegion.HasPolyPolygonOrB2DPolyPolygon() )
1310 aMtf.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion.GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) );
1311 else
1313 pAction->Duplicate();
1314 aMtf.AddAction( pAction );
1317 break;
1319 case( MetaActionType::REFPOINT ):
1321 MetaRefPointAction* pAct = static_cast<MetaRefPointAction*>(pAction);
1322 aMtf.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct->GetRefPoint(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->IsSetting() ) );
1324 break;
1326 case( MetaActionType::FONT ):
1328 MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
1329 vcl::Font aFont( pAct->GetFont() );
1331 aFont.SetOrientation( aFont.GetOrientation() + (sal_uInt16) nAngle10 );
1332 aMtf.AddAction( new MetaFontAction( aFont ) );
1334 break;
1336 case( MetaActionType::BMP ):
1337 case( MetaActionType::BMPEX ):
1338 case( MetaActionType::MASK ):
1339 case( MetaActionType::MASKSCALE ):
1340 case( MetaActionType::MASKSCALEPART ):
1341 case( MetaActionType::WALLPAPER ):
1342 case( MetaActionType::TEXTRECT ):
1343 case( MetaActionType::MOVECLIPREGION ):
1345 OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
1347 break;
1349 default:
1351 pAction->Execute( aMapVDev.get() );
1352 pAction->Duplicate();
1353 aMtf.AddAction( pAction );
1355 // update rotation point and offset, if necessary
1356 if( ( MetaActionType::MAPMODE == nActionType ) ||
1357 ( MetaActionType::PUSH == nActionType ) ||
1358 ( MetaActionType::POP == nActionType ) )
1360 aRotAnchor = OutputDevice::LogicToLogic( aOrigin, aPrefMapMode, aMapVDev->GetMapMode() );
1361 aRotOffset = OutputDevice::LogicToLogic( aOffset, aPrefMapMode, aMapVDev->GetMapMode() );
1364 break;
1368 aMtf.aPrefMapMode = aPrefMapMode;
1369 aMtf.aPrefSize = aNewBound.GetSize();
1371 *this = aMtf;
1375 static void ImplActionBounds( Rectangle& o_rOutBounds,
1376 const Rectangle& i_rInBounds,
1377 const std::vector<Rectangle>& i_rClipStack,
1378 Rectangle* o_pHairline )
1380 Rectangle aBounds( i_rInBounds );
1381 if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() )
1382 aBounds.Intersection( i_rClipStack.back() );
1383 if( ! aBounds.IsEmpty() )
1385 if( ! o_rOutBounds.IsEmpty() )
1386 o_rOutBounds.Union( aBounds );
1387 else
1388 o_rOutBounds = aBounds;
1390 if(o_pHairline)
1392 if( ! o_pHairline->IsEmpty() )
1393 o_pHairline->Union( aBounds );
1394 else
1395 *o_pHairline = aBounds;
1400 Rectangle GDIMetaFile::GetBoundRect( OutputDevice& i_rReference, Rectangle* pHairline ) const
1402 GDIMetaFile aMtf;
1403 ScopedVclPtrInstance< VirtualDevice > aMapVDev( i_rReference );
1405 aMapVDev->EnableOutput( false );
1406 aMapVDev->SetMapMode( GetPrefMapMode() );
1408 std::vector<Rectangle> aClipStack( 1, Rectangle() );
1409 std::vector<PushFlags> aPushFlagStack;
1411 Rectangle aBound;
1413 if(pHairline)
1414 *pHairline = Rectangle();
1416 const sal_uLong nCount(GetActionSize());
1418 for(sal_uLong a(0); a < nCount; a++)
1420 MetaAction* pAction = GetAction(a);
1421 const MetaActionType nActionType = pAction->GetType();
1422 Rectangle* pUseHairline = (pHairline && aMapVDev->IsLineColor()) ? pHairline : 0;
1424 switch( nActionType )
1426 case( MetaActionType::PIXEL ):
1428 MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1429 ImplActionBounds( aBound,
1430 Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1431 aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1432 aClipStack, pUseHairline );
1434 break;
1436 case( MetaActionType::POINT ):
1438 MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
1439 ImplActionBounds( aBound,
1440 Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1441 aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1442 aClipStack, pUseHairline );
1444 break;
1446 case( MetaActionType::LINE ):
1448 MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
1449 Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() );
1450 Rectangle aRect( aP1, aP2 );
1451 aRect.Justify();
1453 if(pUseHairline)
1455 const LineInfo& rLineInfo = pAct->GetLineInfo();
1457 if(0 != rLineInfo.GetWidth())
1458 pUseHairline = 0;
1461 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1463 break;
1465 case( MetaActionType::RECT ):
1467 MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
1468 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1470 break;
1472 case( MetaActionType::ROUNDRECT ):
1474 MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
1475 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1477 break;
1479 case( MetaActionType::ELLIPSE ):
1481 MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
1482 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1484 break;
1486 case( MetaActionType::ARC ):
1488 MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
1489 // FIXME: this is imprecise
1490 // e.g. for small arcs the whole rectangle is WAY too large
1491 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1493 break;
1495 case( MetaActionType::PIE ):
1497 MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
1498 // FIXME: this is imprecise
1499 // e.g. for small arcs the whole rectangle is WAY too large
1500 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1502 break;
1504 case( MetaActionType::CHORD ):
1506 MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
1507 // FIXME: this is imprecise
1508 // e.g. for small arcs the whole rectangle is WAY too large
1509 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1511 break;
1513 case( MetaActionType::POLYLINE ):
1515 MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
1516 Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1518 if(pUseHairline)
1520 const LineInfo& rLineInfo = pAct->GetLineInfo();
1522 if(0 != rLineInfo.GetWidth())
1523 pUseHairline = 0;
1526 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1528 break;
1530 case( MetaActionType::POLYGON ):
1532 MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
1533 Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1534 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1536 break;
1538 case( MetaActionType::POLYPOLYGON ):
1540 MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
1541 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1542 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1544 break;
1546 case( MetaActionType::TEXT ):
1548 MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
1549 Rectangle aRect;
1550 // hdu said base = index
1551 aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() );
1552 Point aPt( pAct->GetPoint() );
1553 aRect.Move( aPt.X(), aPt.Y() );
1554 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1556 break;
1558 case( MetaActionType::TEXTARRAY ):
1560 MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
1561 Rectangle aRect;
1562 // hdu said base = index
1563 aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1564 0, pAct->GetDXArray() );
1565 Point aPt( pAct->GetPoint() );
1566 aRect.Move( aPt.X(), aPt.Y() );
1567 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1569 break;
1571 case( MetaActionType::STRETCHTEXT ):
1573 MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
1574 Rectangle aRect;
1575 // hdu said base = index
1576 aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1577 pAct->GetWidth(), NULL );
1578 Point aPt( pAct->GetPoint() );
1579 aRect.Move( aPt.X(), aPt.Y() );
1580 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1582 break;
1584 case( MetaActionType::TEXTLINE ):
1586 MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
1587 // measure a test string to get ascend and descent right
1588 static const sal_Unicode pStr[] = { 0xc4, 0x67, 0 };
1589 OUString aStr( pStr );
1591 Rectangle aRect;
1592 aMapVDev->GetTextBoundRect( aRect, aStr, 0, 0, aStr.getLength(), 0, NULL );
1593 Point aPt( pAct->GetStartPoint() );
1594 aRect.Move( aPt.X(), aPt.Y() );
1595 aRect.Right() = aRect.Left() + pAct->GetWidth();
1596 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1598 break;
1600 case( MetaActionType::BMPSCALE ):
1602 MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1603 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1604 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1606 break;
1608 case( MetaActionType::BMPSCALEPART ):
1610 MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1611 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1612 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1614 break;
1616 case( MetaActionType::BMPEXSCALE ):
1618 MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1619 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1620 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1622 break;
1624 case( MetaActionType::BMPEXSCALEPART ):
1626 MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1627 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1628 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1630 break;
1632 case( MetaActionType::GRADIENT ):
1634 MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1635 Rectangle aRect( pAct->GetRect() );
1636 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1638 break;
1640 case( MetaActionType::GRADIENTEX ):
1642 MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1643 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1644 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1646 break;
1648 case( MetaActionType::COMMENT ):
1650 // nothing to do
1652 break;
1654 case( MetaActionType::HATCH ):
1656 MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1657 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1658 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1660 break;
1662 case( MetaActionType::Transparent ):
1664 MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1665 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1666 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1668 break;
1670 case( MetaActionType::FLOATTRANSPARENT ):
1672 MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1673 // MetaFloatTransparentAction is defined limiting it's content Metafile
1674 // to it's geometry definition(Point, Size), so use these directly
1675 const Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1676 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1678 break;
1680 case( MetaActionType::EPS ):
1682 MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1683 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1684 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1686 break;
1688 case( MetaActionType::CLIPREGION ):
1690 MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1691 if( pAct->IsClipping() )
1692 aClipStack.back() = OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() );
1693 else
1694 aClipStack.back() = Rectangle();
1696 break;
1698 case( MetaActionType::ISECTRECTCLIPREGION ):
1700 MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1701 Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1702 if( aClipStack.back().IsEmpty() )
1703 aClipStack.back() = aRect;
1704 else
1705 aClipStack.back().Intersection( aRect );
1707 break;
1709 case( MetaActionType::ISECTREGIONCLIPREGION ):
1711 MetaISectRegionClipRegionAction* pAct = static_cast<MetaISectRegionClipRegionAction*>(pAction);
1712 Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1713 if( aClipStack.back().IsEmpty() )
1714 aClipStack.back() = aRect;
1715 else
1716 aClipStack.back().Intersection( aRect );
1718 break;
1720 case( MetaActionType::BMP ):
1722 MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pAction);
1723 Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1724 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1726 break;
1728 case( MetaActionType::BMPEX ):
1730 MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pAction);
1731 Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) );
1732 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1734 break;
1736 case( MetaActionType::MASK ):
1738 MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pAction);
1739 Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1740 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1742 break;
1744 case( MetaActionType::MASKSCALE ):
1746 MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1747 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1748 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1750 break;
1752 case( MetaActionType::MASKSCALEPART ):
1754 MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1755 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1756 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1758 break;
1760 case( MetaActionType::WALLPAPER ):
1762 MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
1763 Rectangle aRect( pAct->GetRect() );
1764 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1766 break;
1768 case( MetaActionType::TEXTRECT ):
1770 MetaTextRectAction* pAct = static_cast<MetaTextRectAction*>(pAction);
1771 Rectangle aRect( pAct->GetRect() );
1772 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1774 break;
1776 case( MetaActionType::MOVECLIPREGION ):
1778 MetaMoveClipRegionAction* pAct = static_cast<MetaMoveClipRegionAction*>(pAction);
1779 if( ! aClipStack.back().IsEmpty() )
1781 Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() );
1782 aDelta = OutputDevice::LogicToLogic( aDelta, aMapVDev->GetMapMode(), GetPrefMapMode() );
1783 aClipStack.back().Move( aDelta.Width(), aDelta.Width() );
1786 break;
1788 default:
1790 pAction->Execute( aMapVDev.get() );
1792 if( nActionType == MetaActionType::PUSH )
1794 MetaPushAction* pAct = static_cast<MetaPushAction*>(pAction);
1795 aPushFlagStack.push_back( pAct->GetFlags() );
1796 if( aPushFlagStack.back() & PushFlags::CLIPREGION )
1798 Rectangle aRect( aClipStack.back() );
1799 aClipStack.push_back( aRect );
1802 else if( nActionType == MetaActionType::POP )
1804 // sanity check
1805 if( ! aPushFlagStack.empty() )
1807 if( aPushFlagStack.back() & PushFlags::CLIPREGION )
1809 if( aClipStack.size() > 1 )
1810 aClipStack.pop_back();
1812 aPushFlagStack.pop_back();
1816 break;
1819 return aBound;
1822 Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
1824 return Color( rColor.GetTransparency(),
1825 static_cast<const ImplColAdjustParam*>(pColParam)->pMapR[ rColor.GetRed() ],
1826 static_cast<const ImplColAdjustParam*>(pColParam)->pMapG[ rColor.GetGreen() ],
1827 static_cast<const ImplColAdjustParam*>(pColParam)->pMapB[ rColor.GetBlue() ] );
1831 BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1833 const ImplBmpAdjustParam* p = static_cast<const ImplBmpAdjustParam*>(pBmpParam);
1834 BitmapEx aRet( rBmpEx );
1836 aRet.Adjust( p->nLuminancePercent, p->nContrastPercent,
1837 p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent,
1838 p->fGamma, p->bInvert );
1840 return aRet;
1843 Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam )
1845 sal_uInt8 cLum = rColor.GetLuminance();
1847 if( MTF_CONVERSION_1BIT_THRESHOLD == static_cast<const ImplColConvertParam*>(pColParam)->eConversion )
1848 cLum = ( cLum < 128 ) ? 0 : 255;
1850 return Color( rColor.GetTransparency(), cLum, cLum, cLum );
1853 BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1855 BitmapEx aRet( rBmpEx );
1857 aRet.Convert( static_cast<const ImplBmpConvertParam*>(pBmpParam)->eConversion );
1859 return aRet;
1862 Color GDIMetaFile::ImplColMonoFnc( const Color&, const void* pColParam )
1864 return static_cast<const ImplColMonoParam*>(pColParam)->aColor;
1867 BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1869 BitmapPalette aPal( 3 );
1871 aPal[ 0 ] = Color( COL_BLACK );
1872 aPal[ 1 ] = Color( COL_WHITE );
1873 aPal[ 2 ] = static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor;
1875 Bitmap aBmp( rBmpEx.GetSizePixel(), 4, &aPal );
1876 aBmp.Erase( static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor );
1878 if( rBmpEx.IsAlpha() )
1879 return BitmapEx( aBmp, rBmpEx.GetAlpha() );
1880 else if( rBmpEx.IsTransparent() )
1881 return BitmapEx( aBmp, rBmpEx.GetMask() );
1882 else
1883 return aBmp;
1886 Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam )
1888 const sal_uLong nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue();
1890 for( sal_uLong i = 0; i < static_cast<const ImplColReplaceParam*>(pColParam)->nCount; i++ )
1892 if( ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinR[ i ] <= nR ) &&
1893 ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxR[ i ] >= nR ) &&
1894 ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinG[ i ] <= nG ) &&
1895 ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxG[ i ] >= nG ) &&
1896 ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinB[ i ] <= nB ) &&
1897 ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxB[ i ] >= nB ) )
1899 return static_cast<const ImplColReplaceParam*>(pColParam)->pDstCols[ i ];
1903 return rColor;
1906 BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1908 const ImplBmpReplaceParam* p = static_cast<const ImplBmpReplaceParam*>(pBmpParam);
1909 BitmapEx aRet( rBmpEx );
1911 aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount, p->pTols );
1913 return aRet;
1916 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam,
1917 BmpExchangeFnc pFncBmp, const void* pBmpParam )
1919 GDIMetaFile aMtf;
1921 aMtf.aPrefSize = aPrefSize;
1922 aMtf.aPrefMapMode = aPrefMapMode;
1923 aMtf.bUseCanvas = bUseCanvas;
1925 for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
1927 const MetaActionType nType = pAction->GetType();
1929 switch( nType )
1931 case( MetaActionType::PIXEL ):
1933 MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1934 aMtf.push_back( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ) );
1936 break;
1938 case( MetaActionType::LINECOLOR ):
1940 MetaLineColorAction* pAct = static_cast<MetaLineColorAction*>(pAction);
1942 if( !pAct->IsSetting() )
1943 pAct->Duplicate();
1944 else
1945 pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1947 aMtf.push_back( pAct );
1949 break;
1951 case( MetaActionType::FILLCOLOR ):
1953 MetaFillColorAction* pAct = static_cast<MetaFillColorAction*>(pAction);
1955 if( !pAct->IsSetting() )
1956 pAct->Duplicate();
1957 else
1958 pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1960 aMtf.push_back( pAct );
1962 break;
1964 case( MetaActionType::TEXTCOLOR ):
1966 MetaTextColorAction* pAct = static_cast<MetaTextColorAction*>(pAction);
1967 aMtf.push_back( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ) );
1969 break;
1971 case( MetaActionType::TEXTFILLCOLOR ):
1973 MetaTextFillColorAction* pAct = static_cast<MetaTextFillColorAction*>(pAction);
1975 if( !pAct->IsSetting() )
1976 pAct->Duplicate();
1977 else
1978 pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1980 aMtf.push_back( pAct );
1982 break;
1984 case( MetaActionType::TEXTLINECOLOR ):
1986 MetaTextLineColorAction* pAct = static_cast<MetaTextLineColorAction*>(pAction);
1988 if( !pAct->IsSetting() )
1989 pAct->Duplicate();
1990 else
1991 pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1993 aMtf.push_back( pAct );
1995 break;
1997 case( MetaActionType::OVERLINECOLOR ):
1999 MetaOverlineColorAction* pAct = static_cast<MetaOverlineColorAction*>(pAction);
2001 if( !pAct->IsSetting() )
2002 pAct->Duplicate();
2003 else
2004 pAct = new MetaOverlineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
2006 aMtf.push_back( pAct );
2008 break;
2010 case( MetaActionType::FONT ):
2012 MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
2013 vcl::Font aFont( pAct->GetFont() );
2015 aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) );
2016 aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) );
2017 aMtf.push_back( new MetaFontAction( aFont ) );
2019 break;
2021 case( MetaActionType::WALLPAPER ):
2023 MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
2024 Wallpaper aWall( pAct->GetWallpaper() );
2025 const Rectangle& rRect = pAct->GetRect();
2027 aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) );
2029 if( aWall.IsBitmap() )
2030 aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) );
2032 if( aWall.IsGradient() )
2034 Gradient aGradient( aWall.GetGradient() );
2036 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2037 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2038 aWall.SetGradient( aGradient );
2041 aMtf.push_back( new MetaWallpaperAction( rRect, aWall ) );
2043 break;
2045 case( MetaActionType::BMP ):
2046 case( MetaActionType::BMPEX ):
2047 case( MetaActionType::MASK ):
2049 OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
2051 break;
2053 case( MetaActionType::BMPSCALE ):
2055 MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
2056 aMtf.push_back( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(),
2057 pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ) );
2059 break;
2061 case( MetaActionType::BMPSCALEPART ):
2063 MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
2064 aMtf.push_back( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2065 pAct->GetSrcPoint(), pAct->GetSrcSize(),
2066 pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() )
2069 break;
2071 case( MetaActionType::BMPEXSCALE ):
2073 MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
2074 aMtf.push_back( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(),
2075 pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
2078 break;
2080 case( MetaActionType::BMPEXSCALEPART ):
2082 MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
2083 aMtf.push_back( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2084 pAct->GetSrcPoint(), pAct->GetSrcSize(),
2085 pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
2088 break;
2090 case( MetaActionType::MASKSCALE ):
2092 MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pAction);
2093 aMtf.push_back( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(),
2094 pAct->GetBitmap(),
2095 pFncCol( pAct->GetColor(), pColParam ) )
2098 break;
2100 case( MetaActionType::MASKSCALEPART ):
2102 MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
2103 aMtf.push_back( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2104 pAct->GetSrcPoint(), pAct->GetSrcSize(),
2105 pAct->GetBitmap(),
2106 pFncCol( pAct->GetColor(), pColParam ) )
2109 break;
2111 case( MetaActionType::GRADIENT ):
2113 MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
2114 Gradient aGradient( pAct->GetGradient() );
2116 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2117 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2118 aMtf.push_back( new MetaGradientAction( pAct->GetRect(), aGradient ) );
2120 break;
2122 case( MetaActionType::GRADIENTEX ):
2124 MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
2125 Gradient aGradient( pAct->GetGradient() );
2127 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2128 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2129 aMtf.push_back( new MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ) );
2131 break;
2133 case( MetaActionType::HATCH ):
2135 MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
2136 Hatch aHatch( pAct->GetHatch() );
2138 aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) );
2139 aMtf.push_back( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ) );
2141 break;
2143 case( MetaActionType::FLOATTRANSPARENT ):
2145 MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
2146 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
2148 aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2149 aMtf.push_back( new MetaFloatTransparentAction( aTransMtf,
2150 pAct->GetPoint(), pAct->GetSize(),
2151 pAct->GetGradient() )
2154 break;
2156 case( MetaActionType::EPS ):
2158 MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
2159 GDIMetaFile aSubst( pAct->GetSubstitute() );
2161 aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2162 aMtf.push_back( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(),
2163 pAct->GetLink(), aSubst )
2166 break;
2168 default:
2170 pAction->Duplicate();
2171 aMtf.push_back( pAction );
2173 break;
2177 *this = aMtf;
2180 void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
2181 short nChannelRPercent, short nChannelGPercent,
2182 short nChannelBPercent, double fGamma, bool bInvert, bool msoBrightness )
2184 // nothing to do? => return quickly
2185 if( nLuminancePercent || nContrastPercent ||
2186 nChannelRPercent || nChannelGPercent || nChannelBPercent ||
2187 ( fGamma != 1.0 ) || bInvert )
2189 double fM, fROff, fGOff, fBOff, fOff;
2190 ImplColAdjustParam aColParam;
2191 ImplBmpAdjustParam aBmpParam;
2193 aColParam.pMapR = new sal_uInt8[ 256 ];
2194 aColParam.pMapG = new sal_uInt8[ 256 ];
2195 aColParam.pMapB = new sal_uInt8[ 256 ];
2197 // calculate slope
2198 if( nContrastPercent >= 0 )
2199 fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
2200 else
2201 fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
2203 if(!msoBrightness)
2204 // total offset = luminance offset + contrast offset
2205 fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
2206 else
2207 fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55;
2209 // channel offset = channel offset + total offset
2210 fROff = nChannelRPercent * 2.55 + fOff;
2211 fGOff = nChannelGPercent * 2.55 + fOff;
2212 fBOff = nChannelBPercent * 2.55 + fOff;
2214 // calculate gamma value
2215 fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
2216 const bool bGamma = ( fGamma != 1.0 );
2218 // create mapping table
2219 for( long nX = 0L; nX < 256L; nX++ )
2221 if(!msoBrightness)
2223 aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
2224 aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
2225 aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
2227 else
2229 aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0L, 255L );
2230 aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0L, 255L );
2231 aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0L, 255L );
2233 if( bGamma )
2235 aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma );
2236 aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma );
2237 aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma );
2240 if( bInvert )
2242 aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ];
2243 aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ];
2244 aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ];
2248 aBmpParam.nLuminancePercent = nLuminancePercent;
2249 aBmpParam.nContrastPercent = nContrastPercent;
2250 aBmpParam.nChannelRPercent = nChannelRPercent;
2251 aBmpParam.nChannelGPercent = nChannelGPercent;
2252 aBmpParam.nChannelBPercent = nChannelBPercent;
2253 aBmpParam.fGamma = fGamma;
2254 aBmpParam.bInvert = bInvert;
2256 // do color adjustment
2257 ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam );
2259 delete[] aColParam.pMapR;
2260 delete[] aColParam.pMapG;
2261 delete[] aColParam.pMapB;
2265 void GDIMetaFile::Convert( MtfConversion eConversion )
2267 // nothing to do? => return quickly
2268 if( eConversion != MTF_CONVERSION_NONE )
2270 ImplColConvertParam aColParam;
2271 ImplBmpConvertParam aBmpParam;
2273 aColParam.eConversion = eConversion;
2274 aBmpParam.eConversion = ( MTF_CONVERSION_1BIT_THRESHOLD == eConversion ) ? BMP_CONVERSION_1BIT_THRESHOLD : BMP_CONVERSION_8BIT_GREYS;
2276 ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam );
2280 void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, sal_uLong* pTols )
2282 ImplColReplaceParam aColParam;
2283 ImplBmpReplaceParam aBmpParam;
2285 aColParam.pMinR = new sal_uLong[ nColorCount ];
2286 aColParam.pMaxR = new sal_uLong[ nColorCount ];
2287 aColParam.pMinG = new sal_uLong[ nColorCount ];
2288 aColParam.pMaxG = new sal_uLong[ nColorCount ];
2289 aColParam.pMinB = new sal_uLong[ nColorCount ];
2290 aColParam.pMaxB = new sal_uLong[ nColorCount ];
2292 for( sal_uLong i = 0; i < nColorCount; i++ )
2294 const long nTol = pTols ? ( pTols[ i ] * 255 ) / 100 : 0;
2295 long nVal;
2297 nVal = pSearchColors[ i ].GetRed();
2298 aColParam.pMinR[ i ] = (sal_uLong) std::max( nVal - nTol, 0L );
2299 aColParam.pMaxR[ i ] = (sal_uLong) std::min( nVal + nTol, 255L );
2301 nVal = pSearchColors[ i ].GetGreen();
2302 aColParam.pMinG[ i ] = (sal_uLong) std::max( nVal - nTol, 0L );
2303 aColParam.pMaxG[ i ] = (sal_uLong) std::min( nVal + nTol, 255L );
2305 nVal = pSearchColors[ i ].GetBlue();
2306 aColParam.pMinB[ i ] = (sal_uLong) std::max( nVal - nTol, 0L );
2307 aColParam.pMaxB[ i ] = (sal_uLong) std::min( nVal + nTol, 255L );
2310 aColParam.pDstCols = pReplaceColors;
2311 aColParam.nCount = nColorCount;
2313 aBmpParam.pSrcCols = pSearchColors;
2314 aBmpParam.pDstCols = pReplaceColors;
2315 aBmpParam.nCount = nColorCount;
2316 aBmpParam.pTols = pTols;
2318 ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam );
2320 delete[] aColParam.pMinR;
2321 delete[] aColParam.pMaxR;
2322 delete[] aColParam.pMinG;
2323 delete[] aColParam.pMaxG;
2324 delete[] aColParam.pMinB;
2325 delete[] aColParam.pMaxB;
2328 GDIMetaFile GDIMetaFile::GetMonochromeMtf( const Color& rColor ) const
2330 GDIMetaFile aRet( *this );
2332 ImplColMonoParam aColParam;
2333 ImplBmpMonoParam aBmpParam;
2335 aColParam.aColor = rColor;
2336 aBmpParam.aColor = rColor;
2338 aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam );
2340 return aRet;
2343 BitmapChecksum GDIMetaFile::GetChecksum() const
2345 GDIMetaFile aMtf;
2346 SvMemoryStream aMemStm( 65535, 65535 );
2347 ImplMetaWriteData aWriteData;
2348 SVBT16 aBT16;
2349 SVBT32 aBT32;
2350 BitmapChecksumOctetArray aBCOA;
2351 BitmapChecksum nCrc = 0;
2353 aWriteData.meActualCharSet = aMemStm.GetStreamCharSet();
2354 for( size_t i = 0, nObjCount = GetActionSize(); i < nObjCount; i++ )
2356 MetaAction* pAction = GetAction( i );
2358 switch( pAction->GetType() )
2360 case( MetaActionType::BMP ):
2362 MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pAction);
2364 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2365 nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2367 BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2368 nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2370 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2371 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2373 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2374 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2376 break;
2378 case( MetaActionType::BMPSCALE ):
2380 MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
2382 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2383 nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2385 BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2386 nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2388 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2389 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2391 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2392 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2394 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2395 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2397 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2398 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2400 break;
2402 case( MetaActionType::BMPSCALEPART ):
2404 MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
2406 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2407 nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2409 BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2410 nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2412 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2413 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2415 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2416 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2418 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2419 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2421 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2422 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2424 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2425 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2427 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2428 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2430 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2431 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2433 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2434 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2436 break;
2438 case( MetaActionType::BMPEX ):
2440 MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pAction);
2442 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2443 nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2445 BCToBCOA( pAct->GetBitmapEx().GetChecksum(), aBCOA );
2446 nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2448 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2449 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2451 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2452 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2454 break;
2456 case( MetaActionType::BMPEXSCALE ):
2458 MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
2460 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2461 nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2463 BCToBCOA( pAct->GetBitmapEx().GetChecksum(), aBCOA );
2464 nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2466 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2467 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2469 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2470 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2472 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2473 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2475 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2476 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2478 break;
2480 case( MetaActionType::BMPEXSCALEPART ):
2482 MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
2484 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2485 nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2487 BCToBCOA( pAct->GetBitmapEx().GetChecksum(), aBCOA );
2488 nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2490 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2491 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2493 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2494 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2496 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2497 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2499 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2500 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2502 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2503 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2505 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2506 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2508 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2509 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2511 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2512 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2514 break;
2516 case( MetaActionType::MASK ):
2518 MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pAction);
2520 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2521 nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2523 BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2524 nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2526 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2527 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2529 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2530 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2532 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2533 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2535 break;
2537 case( MetaActionType::MASKSCALE ):
2539 MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pAction);
2541 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2542 nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2544 BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2545 nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2547 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2548 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2550 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2551 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2553 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2554 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2556 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2557 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2559 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2560 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2562 break;
2564 case( MetaActionType::MASKSCALEPART ):
2566 MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
2568 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2569 nCrc = vcl_get_checksum( nCrc, aBT16, 2 );
2571 BCToBCOA( pAct->GetBitmap().GetChecksum(), aBCOA );
2572 nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
2574 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2575 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2577 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2578 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2580 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2581 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2583 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2584 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2586 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2587 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2589 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2590 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2592 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2593 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2595 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2596 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2598 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2599 nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
2601 break;
2603 case MetaActionType::EPS :
2605 MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
2606 nCrc = vcl_get_checksum( nCrc, pAct->GetLink().GetData(), pAct->GetLink().GetDataSize() );
2608 break;
2610 case MetaActionType::CLIPREGION :
2612 MetaClipRegionAction& rAct = static_cast<MetaClipRegionAction&>(*pAction);
2613 const vcl::Region& rRegion = rAct.GetRegion();
2615 if(rRegion.HasPolyPolygonOrB2DPolyPolygon())
2617 // It has shown that this is a possible bottleneck for checksum calculation.
2618 // In worst case a very expensive RegionHandle representation gets created.
2619 // In this case it's cheaper to use the PolyPolygon
2620 const basegfx::B2DPolyPolygon aPolyPolygon(rRegion.GetAsB2DPolyPolygon());
2621 const sal_uInt32 nPolyCount(aPolyPolygon.count());
2622 SVBT64 aSVBT64;
2624 for(sal_uInt32 a(0); a < nPolyCount; a++)
2626 const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(a));
2627 const sal_uInt32 nPointCount(aPolygon.count());
2628 const bool bControl(aPolygon.areControlPointsUsed());
2630 for(sal_uInt32 b(0); b < nPointCount; b++)
2632 const basegfx::B2DPoint aPoint(aPolygon.getB2DPoint(b));
2634 DoubleToSVBT64(aPoint.getX(), aSVBT64);
2635 nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2636 DoubleToSVBT64(aPoint.getY(), aSVBT64);
2637 nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2639 if(bControl)
2641 if(aPolygon.isPrevControlPointUsed(b))
2643 const basegfx::B2DPoint aCtrl(aPolygon.getPrevControlPoint(b));
2645 DoubleToSVBT64(aCtrl.getX(), aSVBT64);
2646 nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2647 DoubleToSVBT64(aCtrl.getY(), aSVBT64);
2648 nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2651 if(aPolygon.isNextControlPointUsed(b))
2653 const basegfx::B2DPoint aCtrl(aPolygon.getNextControlPoint(b));
2655 DoubleToSVBT64(aCtrl.getX(), aSVBT64);
2656 nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2657 DoubleToSVBT64(aCtrl.getY(), aSVBT64);
2658 nCrc = vcl_get_checksum(nCrc, aSVBT64, 8);
2664 sal_uInt8 tmp = (sal_uInt8)rAct.IsClipping();
2665 nCrc = vcl_get_checksum(nCrc, &tmp, 1);
2667 else
2669 pAction->Write( aMemStm, &aWriteData );
2670 nCrc = vcl_get_checksum( nCrc, aMemStm.GetData(), aMemStm.Tell() );
2671 aMemStm.Seek( 0 );
2674 break;
2676 default:
2678 pAction->Write( aMemStm, &aWriteData );
2679 nCrc = vcl_get_checksum( nCrc, aMemStm.GetData(), aMemStm.Tell() );
2680 aMemStm.Seek( 0 );
2682 break;
2686 return nCrc;
2689 sal_uLong GDIMetaFile::GetSizeBytes() const
2691 sal_uLong nSizeBytes = 0;
2693 for( size_t i = 0, nObjCount = GetActionSize(); i < nObjCount; ++i )
2695 MetaAction* pAction = GetAction( i );
2697 // default action size is set to 32 (=> not the exact value)
2698 nSizeBytes += 32;
2700 // add sizes for large action content
2701 switch( pAction->GetType() )
2703 case( MetaActionType::BMP ): nSizeBytes += static_cast<MetaBmpAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2704 case( MetaActionType::BMPSCALE ): nSizeBytes += static_cast<MetaBmpScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2705 case( MetaActionType::BMPSCALEPART ): nSizeBytes += static_cast<MetaBmpScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2707 case( MetaActionType::BMPEX ): nSizeBytes += static_cast<MetaBmpExAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2708 case( MetaActionType::BMPEXSCALE ): nSizeBytes += static_cast<MetaBmpExScaleAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2709 case( MetaActionType::BMPEXSCALEPART ): nSizeBytes += static_cast<MetaBmpExScalePartAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2711 case( MetaActionType::MASK ): nSizeBytes += static_cast<MetaMaskAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2712 case( MetaActionType::MASKSCALE ): nSizeBytes += static_cast<MetaMaskScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2713 case( MetaActionType::MASKSCALEPART ): nSizeBytes += static_cast<MetaMaskScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2715 case( MetaActionType::POLYLINE ): nSizeBytes += static_cast<MetaPolyLineAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2716 case( MetaActionType::POLYGON ): nSizeBytes += static_cast<MetaPolygonAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2717 case( MetaActionType::POLYPOLYGON ):
2719 const tools::PolyPolygon& rPolyPoly = static_cast<MetaPolyPolygonAction*>( pAction )->GetPolyPolygon();
2721 for( sal_uInt16 n = 0; n < rPolyPoly.Count(); ++n )
2722 nSizeBytes += ( rPolyPoly[ n ].GetSize() * sizeof( Point ) );
2724 break;
2726 case( MetaActionType::TEXT ): nSizeBytes += static_cast<MetaTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2727 case( MetaActionType::STRETCHTEXT ): nSizeBytes += static_cast<MetaStretchTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2728 case( MetaActionType::TEXTRECT ): nSizeBytes += static_cast<MetaTextRectAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2729 case( MetaActionType::TEXTARRAY ):
2731 MetaTextArrayAction* pTextArrayAction = static_cast<MetaTextArrayAction*>(pAction);
2733 nSizeBytes += ( pTextArrayAction->GetText().getLength() * sizeof( sal_Unicode ) );
2735 if( pTextArrayAction->GetDXArray() )
2736 nSizeBytes += ( pTextArrayAction->GetLen() << 2 );
2738 break;
2739 default: break;
2743 return nSizeBytes;
2746 SvStream& ReadGDIMetaFile( SvStream& rIStm, GDIMetaFile& rGDIMetaFile )
2748 if( !rIStm.GetError() )
2750 char aId[ 7 ];
2751 sal_uLong nStmPos = rIStm.Tell();
2752 SvStreamEndian nOldFormat = rIStm.GetEndian();
2754 rIStm.SetEndian( SvStreamEndian::LITTLE );
2756 aId[ 0 ] = 0;
2757 aId[ 6 ] = 0;
2758 rIStm.Read( aId, 6 );
2760 if ( !strcmp( aId, "VCLMTF" ) )
2762 // new format
2763 VersionCompat* pCompat;
2764 MetaAction* pAction;
2765 sal_uInt32 nStmCompressMode = 0;
2766 sal_uInt32 nCount = 0;
2768 pCompat = new VersionCompat( rIStm, StreamMode::READ );
2770 rIStm.ReadUInt32( nStmCompressMode );
2771 ReadMapMode( rIStm, rGDIMetaFile.aPrefMapMode );
2772 ReadPair( rIStm, rGDIMetaFile.aPrefSize );
2773 rIStm.ReadUInt32( nCount );
2775 delete pCompat;
2777 ImplMetaReadData aReadData;
2778 aReadData.meActualCharSet = rIStm.GetStreamCharSet();
2780 for( sal_uInt32 nAction = 0UL; ( nAction < nCount ) && !rIStm.IsEof(); nAction++ )
2782 pAction = MetaAction::ReadMetaAction( rIStm, &aReadData );
2784 if( pAction )
2786 if (pAction->GetType() == MetaActionType::COMMENT)
2788 MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
2789 if ( pCommentAct->GetComment() == "EMF_PLUS" )
2790 rGDIMetaFile.UseCanvas( true );
2792 rGDIMetaFile.AddAction( pAction );
2796 else
2798 // to avoid possible compiler optimizations => new/delete
2799 rIStm.Seek( nStmPos );
2800 delete( new SVMConverter( rIStm, rGDIMetaFile, CONVERT_FROM_SVM1 ) );
2803 // check for errors
2804 if( rIStm.GetError() )
2806 rGDIMetaFile.Clear();
2807 rIStm.Seek( nStmPos );
2810 rIStm.SetEndian( nOldFormat );
2812 else
2814 SAL_WARN("vcl.gdi", "Stream error: " << rIStm.GetError());
2817 return rIStm;
2820 SvStream& WriteGDIMetaFile( SvStream& rOStm, const GDIMetaFile& rGDIMetaFile )
2822 if( !rOStm.GetError() )
2824 static const char* pEnableSVM1 = getenv( "SAL_ENABLE_SVM1" );
2825 static const bool bNoSVM1 = (NULL == pEnableSVM1 ) || ( '0' == *pEnableSVM1 );
2827 if( bNoSVM1 || rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 )
2829 const_cast< GDIMetaFile& >( rGDIMetaFile ).Write( rOStm );
2831 else
2833 delete( new SVMConverter( rOStm, const_cast< GDIMetaFile& >( rGDIMetaFile ), CONVERT_TO_SVM1 ) );
2836 #ifdef DEBUG
2837 if( !bNoSVM1 && rOStm.GetVersion() < SOFFICE_FILEFORMAT_50 )
2839 OSL_TRACE( \
2840 "GDIMetaFile would normally be written in old SVM1 format by this call. \
2841 The current implementation always writes in VCLMTF format. \
2842 Please set environment variable SAL_ENABLE_SVM1 to '1' to reenable old behavior" );
2844 #endif // DEBUG
2847 return rOStm;
2850 SvStream& GDIMetaFile::Read( SvStream& rIStm )
2852 Clear();
2853 ReadGDIMetaFile( rIStm, *this );
2855 return rIStm;
2858 SvStream& GDIMetaFile::Write( SvStream& rOStm )
2860 VersionCompat* pCompat;
2861 const SvStreamCompressFlags nStmCompressMode = rOStm.GetCompressMode();
2862 SvStreamEndian nOldFormat = rOStm.GetEndian();
2864 rOStm.SetEndian( SvStreamEndian::LITTLE );
2865 rOStm.Write( "VCLMTF", 6 );
2867 pCompat = new VersionCompat( rOStm, StreamMode::WRITE, 1 );
2869 rOStm.WriteUInt32( static_cast<sal_uInt32>(nStmCompressMode) );
2870 WriteMapMode( rOStm, aPrefMapMode );
2871 WritePair( rOStm, aPrefSize );
2872 rOStm.WriteUInt32( GetActionSize() );
2874 delete pCompat;
2876 ImplMetaWriteData aWriteData;
2878 aWriteData.meActualCharSet = rOStm.GetStreamCharSet();
2880 MetaAction* pAct = FirstAction();
2881 while ( pAct )
2883 pAct->Write( rOStm, &aWriteData );
2884 pAct = NextAction();
2887 rOStm.SetEndian( nOldFormat );
2889 return rOStm;
2892 bool GDIMetaFile::CreateThumbnail(BitmapEx& rBitmapEx, sal_uInt32 nMaximumExtent, BmpConversion eColorConversion, BmpScaleFlag nScaleFlag) const
2894 // initialization seems to be complicated but is used to avoid rounding errors
2895 ScopedVclPtrInstance< VirtualDevice > aVDev;
2896 const Point aNullPt;
2897 const Point aTLPix( aVDev->LogicToPixel( aNullPt, GetPrefMapMode() ) );
2898 const Point aBRPix( aVDev->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
2899 Size aDrawSize( aVDev->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
2900 Size aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 );
2902 if (!rBitmapEx.IsEmpty())
2903 rBitmapEx.SetEmpty();
2905 // determine size that has the same aspect ratio as image size and
2906 // fits into the rectangle determined by nMaximumExtent
2907 if ( aSizePix.Width() && aSizePix.Height()
2908 && ( sal::static_int_cast< unsigned long >(aSizePix.Width()) >
2909 nMaximumExtent ||
2910 sal::static_int_cast< unsigned long >(aSizePix.Height()) >
2911 nMaximumExtent ) )
2913 const Size aOldSizePix( aSizePix );
2914 double fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height();
2916 if ( fWH <= 1.0 )
2918 aSizePix.Width() = FRound( nMaximumExtent * fWH );
2919 aSizePix.Height() = nMaximumExtent;
2921 else
2923 aSizePix.Width() = nMaximumExtent;
2924 aSizePix.Height() = FRound( nMaximumExtent / fWH );
2927 aDrawSize.Width() = FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() );
2928 aDrawSize.Height() = FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() );
2931 // draw image(s) into VDev and get resulting image
2932 // do it 4x larger to be able to scale it down & get beautiful antialias
2933 Size aAntialiasSize(aSizePix.Width() * 4, aSizePix.Height() * 4);
2934 if (aVDev->SetOutputSizePixel(aAntialiasSize))
2936 // antialias: provide 4x larger size, and then scale down the result
2937 Size aAntialias(aDrawSize.Width() * 4, aDrawSize.Height() * 4);
2939 // draw metafile into VDev
2940 Point aBackPosPix;
2941 const_cast<GDIMetaFile *>(this)->WindStart();
2942 const_cast<GDIMetaFile *>(this)->Play(aVDev.get(), aBackPosPix, aAntialias);
2944 // get paint bitmap
2945 Bitmap aBitmap( aVDev->GetBitmap( aNullPt, aVDev->GetOutputSizePixel() ) );
2947 // scale down the image to the desired size - use the input scaler for the scaling operation
2948 aBitmap.Scale(aDrawSize, nScaleFlag);
2950 // convert to desired bitmap color format
2951 aBitmap.Convert(eColorConversion);
2953 rBitmapEx = BitmapEx(aBitmap);
2956 return !rBitmapEx.IsEmpty();
2959 void GDIMetaFile::UseCanvas( bool _bUseCanvas )
2961 bUseCanvas = _bUseCanvas;
2964 MetaCommentAction* makePluggableRendererAction( const OUString& rRendererServiceName,
2965 const OUString& rGraphicServiceName,
2966 const void* _pData,
2967 sal_uInt32 nDataSize )
2969 const sal_uInt8* pData=static_cast<sal_uInt8 const *>(_pData);
2971 // FIXME: Data gets copied twice, unfortunately
2972 OString aRendererServiceName(
2973 rRendererServiceName.getStr(),
2974 rRendererServiceName.getLength(),
2975 RTL_TEXTENCODING_ASCII_US);
2976 OString aGraphicServiceName(
2977 rGraphicServiceName.getStr(),
2978 rGraphicServiceName.getLength(),
2979 RTL_TEXTENCODING_ASCII_US);
2981 std::vector<sal_uInt8> aMem(
2982 aRendererServiceName.getLength()+
2983 aGraphicServiceName.getLength()+2+nDataSize);
2984 sal_uInt8* pMem=&aMem[0];
2986 std::copy(aRendererServiceName.getStr(),
2987 aRendererServiceName.getStr()+aRendererServiceName.getLength()+1,
2988 pMem);
2989 pMem+=aRendererServiceName.getLength()+1;
2990 std::copy(aGraphicServiceName.getStr(),
2991 aGraphicServiceName.getStr()+aGraphicServiceName.getLength()+1,
2992 pMem);
2993 pMem+=aGraphicServiceName.getLength()+1;
2995 std::copy(pData,pData+nDataSize,
2996 pMem);
2998 return new MetaCommentAction(
2999 "DELEGATE_PLUGGABLE_RENDERER",
3001 &aMem[0],
3002 aMem.size());
3005 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */