update dev300-m58
[ooovba.git] / vcl / source / gdi / gdimtf.cxx
blob6bde9c9dfead157a46000d8ce35dbe98cf9e4479
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: gdimtf.cxx,v $
10 * $Revision: 1.24.134.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <vos/macros.hxx>
34 #include <rtl/crc.h>
35 #include <tools/stream.hxx>
36 #include <tools/vcompat.hxx>
37 #include <vcl/metaact.hxx>
38 #include <vcl/salbtype.hxx>
39 #include <vcl/outdev.hxx>
40 #include <vcl/window.hxx>
41 #include <vcl/cvtsvm.hxx>
42 #include <vcl/virdev.hxx>
43 #include <vcl/salbmp.hxx>
44 #include <vcl/svapp.hxx>
45 #include <vcl/svdata.hxx>
46 #include <vcl/salinst.hxx>
47 #include <vcl/gdimtf.hxx>
48 #include <vcl/graphictools.hxx>
49 #include <vcl/canvastools.hxx>
50 #include <vcl/unohelp.hxx>
52 #include <com/sun/star/beans/XFastPropertySet.hpp>
53 #include <com/sun/star/rendering/XCanvas.hpp>
54 #include <com/sun/star/rendering/MtfRenderer.hpp>
55 #include <comphelper/processfactory.hxx>
56 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
57 #include <com/sun/star/lang/XInitialization.hpp>
58 #include <com/sun/star/awt/XGraphics.hpp>
59 #include <com/sun/star/graphic/XGraphic.hpp>
60 #include <com/sun/star/graphic/XGraphicRenderer.hpp>
62 using namespace com::sun::star;
64 // -----------
65 // - Defines -
66 // -----------
68 #define GAMMA( _def_cVal, _def_InvGamma ) ((BYTE)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
70 // --------------------------
71 // - Color exchange structs -
72 // --------------------------
74 struct ImplColAdjustParam
76 BYTE* pMapR;
77 BYTE* pMapG;
78 BYTE* pMapB;
81 struct ImplBmpAdjustParam
83 short nLuminancePercent;
84 short nContrastPercent;
85 short nChannelRPercent;
86 short nChannelGPercent;
87 short nChannelBPercent;
88 double fGamma;
89 BOOL bInvert;
92 // -----------------------------------------------------------------------------
94 struct ImplColConvertParam
96 MtfConversion eConversion;
99 struct ImplBmpConvertParam
101 BmpConversion eConversion;
104 // -----------------------------------------------------------------------------
106 struct ImplColMonoParam
108 Color aColor;
111 struct ImplBmpMonoParam
113 Color aColor;
116 // -----------------------------------------------------------------------------
118 struct ImplColReplaceParam
120 ULONG* pMinR;
121 ULONG* pMaxR;
122 ULONG* pMinG;
123 ULONG* pMaxG;
124 ULONG* pMinB;
125 ULONG* pMaxB;
126 const Color* pDstCols;
127 ULONG nCount;
130 struct ImplBmpReplaceParam
132 const Color* pSrcCols;
133 const Color* pDstCols;
134 ULONG nCount;
135 const ULONG* pTols;
139 // ---------
140 // - Label -
141 // ---------
143 struct ImpLabel
145 String aLabelName;
146 ULONG nActionPos;
148 ImpLabel( const String& rLabelName, ULONG _nActionPos ) :
149 aLabelName( rLabelName ),
150 nActionPos( _nActionPos ) {}
153 // -------------
154 // - LabelList -
155 // -------------
157 class ImpLabelList : private List
159 public:
161 ImpLabelList() : List( 8, 4, 4 ) {}
162 ImpLabelList( const ImpLabelList& rList );
163 ~ImpLabelList();
165 void ImplInsert( ImpLabel* p ) { Insert( p, LIST_APPEND ); }
166 ImpLabel* ImplRemove( ULONG nPos ) { return (ImpLabel*) Remove( nPos ); }
167 void ImplReplace( ImpLabel* p ) { Replace( (void*)p ); }
168 ImpLabel* ImplFirst() { return (ImpLabel*) First(); }
169 ImpLabel* ImplNext() { return (ImpLabel*) Next(); }
170 ImpLabel* ImplGetLabel( ULONG nPos ) const { return (ImpLabel*) GetObject( nPos ); }
171 ULONG ImplGetLabelPos( const String& rLabelName );
172 ULONG ImplCount() const { return Count(); }
175 // ------------------------------------------------------------------------
177 ImpLabelList::ImpLabelList( const ImpLabelList& rList ) :
178 List( rList )
180 for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
181 ImplReplace( new ImpLabel( *pLabel ) );
184 // ------------------------------------------------------------------------
186 ImpLabelList::~ImpLabelList()
188 for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
189 delete pLabel;
192 // ------------------------------------------------------------------------
194 ULONG ImpLabelList::ImplGetLabelPos( const String& rLabelName )
196 ULONG nLabelPos = METAFILE_LABEL_NOTFOUND;
198 for( ImpLabel* pLabel = ImplFirst(); pLabel; pLabel = ImplNext() )
200 if ( rLabelName == pLabel->aLabelName )
202 nLabelPos = GetCurPos();
203 break;
207 return nLabelPos;
210 // ---------------
211 // - GDIMetaFile -
212 // ---------------
214 GDIMetaFile::GDIMetaFile() :
215 List ( 0x3EFF, 64, 64 ),
216 aPrefSize ( 1, 1 ),
217 pPrev ( NULL ),
218 pNext ( NULL ),
219 pOutDev ( NULL ),
220 pLabelList ( NULL ),
221 bPause ( FALSE ),
222 bRecord ( FALSE ),
223 bUseCanvas ( FALSE )
227 // ------------------------------------------------------------------------
229 GDIMetaFile::GDIMetaFile( const GDIMetaFile& rMtf ) :
230 List ( rMtf ),
231 aPrefMapMode ( rMtf.aPrefMapMode ),
232 aPrefSize ( rMtf.aPrefSize ),
233 aHookHdlLink ( rMtf.aHookHdlLink ),
234 pPrev ( rMtf.pPrev ),
235 pNext ( rMtf.pNext ),
236 pOutDev ( NULL ),
237 bPause ( FALSE ),
238 bRecord ( FALSE ),
239 bUseCanvas ( rMtf.bUseCanvas )
241 // RefCount der MetaActions erhoehen
242 for( void* pAct = First(); pAct; pAct = Next() )
243 ( (MetaAction*) pAct )->Duplicate();
245 if( rMtf.pLabelList )
246 pLabelList = new ImpLabelList( *rMtf.pLabelList );
247 else
248 pLabelList = NULL;
250 if( rMtf.bRecord )
252 Record( rMtf.pOutDev );
254 if ( rMtf.bPause )
255 Pause( TRUE );
259 // ------------------------------------------------------------------------
261 GDIMetaFile::~GDIMetaFile()
263 Clear();
266 // ------------------------------------------------------------------------
268 GDIMetaFile& GDIMetaFile::operator=( const GDIMetaFile& rMtf )
270 if( this != &rMtf )
272 Clear();
274 List::operator=( rMtf );
276 // RefCount der MetaActions erhoehen
277 for( void* pAct = First(); pAct; pAct = Next() )
278 ( (MetaAction*) pAct )->Duplicate();
280 if( rMtf.pLabelList )
281 pLabelList = new ImpLabelList( *rMtf.pLabelList );
282 else
283 pLabelList = NULL;
285 aPrefMapMode = rMtf.aPrefMapMode;
286 aPrefSize = rMtf.aPrefSize;
287 aHookHdlLink = rMtf.aHookHdlLink;
288 pPrev = rMtf.pPrev;
289 pNext = rMtf.pNext;
290 pOutDev = NULL;
291 bPause = FALSE;
292 bRecord = FALSE;
293 bUseCanvas = rMtf.bUseCanvas;
295 if( rMtf.bRecord )
297 Record( rMtf.pOutDev );
299 if( rMtf.bPause )
300 Pause( TRUE );
304 return *this;
307 // ------------------------------------------------------------------------
309 BOOL GDIMetaFile::operator==( const GDIMetaFile& rMtf ) const
311 const ULONG nObjCount = Count();
312 BOOL bRet = FALSE;
314 if( this == &rMtf )
315 bRet = TRUE;
316 else if( rMtf.GetActionCount() == nObjCount &&
317 rMtf.GetPrefSize() == aPrefSize &&
318 rMtf.GetPrefMapMode() == aPrefMapMode )
320 bRet = TRUE;
322 for( ULONG n = 0UL; n < nObjCount; n++ )
324 if( GetObject( n ) != rMtf.GetObject( n ) )
326 bRet = FALSE;
327 break;
332 return bRet;
335 // ------------------------------------------------------------------------
337 sal_Bool GDIMetaFile::IsEqual( const GDIMetaFile& rMtf ) const
339 const ULONG nObjCount = Count();
340 BOOL bRet = FALSE;
342 if( this == &rMtf )
343 bRet = TRUE;
344 else if( rMtf.GetActionCount() == nObjCount &&
345 rMtf.GetPrefSize() == aPrefSize &&
346 rMtf.GetPrefMapMode() == aPrefMapMode )
348 bRet = TRUE;
350 for( ULONG n = 0UL; n < nObjCount; n++ )
352 if(!((MetaAction*)GetObject( n ))->IsEqual(*((MetaAction*)rMtf.GetObject( n ))))
354 bRet = FALSE;
355 break;
360 return bRet;
363 // ------------------------------------------------------------------------
365 void GDIMetaFile::Clear()
367 if( bRecord )
368 Stop();
370 for( void* pAct = First(); pAct; pAct = Next() )
371 ( (MetaAction*) pAct )->Delete();
373 List::Clear();
375 delete pLabelList;
376 pLabelList = NULL;
379 // ------------------------------------------------------------------------
381 void GDIMetaFile::Linker( OutputDevice* pOut, BOOL bLink )
383 if( bLink )
385 pNext = NULL;
386 pPrev = pOut->GetConnectMetaFile();
387 pOut->SetConnectMetaFile( this );
389 if( pPrev )
390 pPrev->pNext = this;
392 else
394 if( pNext )
396 pNext->pPrev = pPrev;
398 if( pPrev )
399 pPrev->pNext = pNext;
401 else
403 if( pPrev )
404 pPrev->pNext = NULL;
406 pOut->SetConnectMetaFile( pPrev );
409 pPrev = NULL;
410 pNext = NULL;
414 // ------------------------------------------------------------------------
416 long GDIMetaFile::Hook()
418 return aHookHdlLink.Call( this );
421 // ------------------------------------------------------------------------
423 void GDIMetaFile::Record( OutputDevice* pOut )
425 if( bRecord )
426 Stop();
428 Last();
429 pOutDev = pOut;
430 bRecord = TRUE;
431 Linker( pOut, TRUE );
434 // ------------------------------------------------------------------------
436 void GDIMetaFile::Play( GDIMetaFile& rMtf, ULONG nPos )
438 if ( !bRecord && !rMtf.bRecord )
440 MetaAction* pAction = GetCurAction();
441 const ULONG nObjCount = Count();
443 if( nPos > nObjCount )
444 nPos = nObjCount;
446 for( ULONG nCurPos = GetCurPos(); nCurPos < nPos; nCurPos++ )
448 if( !Hook() )
450 pAction->Duplicate();
451 rMtf.AddAction( pAction );
454 pAction = (MetaAction*) Next();
459 // ------------------------------------------------------------------------
461 void GDIMetaFile::Play( OutputDevice* pOut, ULONG nPos )
463 if( !bRecord )
465 MetaAction* pAction = GetCurAction();
466 const ULONG nObjCount = Count();
467 ULONG i = 0, nSyncCount = ( pOut->GetOutDevType() == OUTDEV_WINDOW ) ? 0x000000ff : 0xffffffff;
469 if( nPos > nObjCount )
470 nPos = nObjCount;
472 // #i23407# Set backwards-compatible text language and layout mode
473 // This is necessary, since old metafiles don't even know of these
474 // recent add-ons. Newer metafiles must of course explicitely set
475 // those states.
476 pOut->Push( PUSH_TEXTLAYOUTMODE|PUSH_TEXTLANGUAGE );
477 pOut->SetLayoutMode( 0 );
478 pOut->SetDigitLanguage( 0 );
480 for( ULONG nCurPos = GetCurPos(); nCurPos < nPos; nCurPos++ )
482 if( !Hook() )
484 MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
485 if( pAction->GetType() == META_COMMENT_ACTION &&
486 pCommentAct->GetComment().Equals("DELEGATE_PLUGGABLE_RENDERER") )
488 ImplDelegate2PluggableRenderer(pCommentAct, pOut);
490 else
492 pAction->Execute( pOut );
495 // flush output from time to time
496 if( i++ > nSyncCount )
497 ( (Window*) pOut )->Flush(), i = 0;
500 pAction = (MetaAction*) Next();
503 pOut->Pop();
507 // ------------------------------------------------------------------------
509 bool GDIMetaFile::ImplPlayWithRenderer( OutputDevice* pOut, const Point& rPos, Size rDestSize )
511 const Window* win = dynamic_cast <Window*> ( pOut );
513 if (!win)
514 win = Application::GetActiveTopWindow();
515 if (!win)
516 win = Application::GetFirstTopLevelWindow();
518 if (win) {
519 const uno::Reference<rendering::XCanvas>& xCanvas = win->GetCanvas ();
520 Size aSize (rDestSize.Width () + 1, rDestSize.Height () + 1);
521 const uno::Reference<rendering::XBitmap>& xBitmap = xCanvas->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize));
522 uno::Reference< lang::XMultiServiceFactory > xFactory = vcl::unohelper::GetMultiServiceFactory();
523 if( xFactory.is() && xBitmap.is () ) {
524 uno::Reference< rendering::XMtfRenderer > xMtfRenderer;
525 uno::Sequence< uno::Any > args (1);
526 uno::Reference< rendering::XBitmapCanvas > xBitmapCanvas( xBitmap, uno::UNO_QUERY );
527 if( xBitmapCanvas.is() ) {
528 args[0] = uno::Any( xBitmapCanvas );
529 xMtfRenderer.set( xFactory->createInstanceWithArguments( ::rtl::OUString::createFromAscii( "com.sun.star.rendering.MtfRenderer" ),
530 args ), uno::UNO_QUERY );
532 if( xMtfRenderer.is() ) {
533 xBitmapCanvas->clear();
534 uno::Reference< beans::XFastPropertySet > xMtfFastPropertySet( xMtfRenderer, uno::UNO_QUERY );
535 if( xMtfFastPropertySet.is() )
536 // set this metafile to the renderer to
537 // speedup things (instead of copying data to
538 // sequence of bytes passed to renderer)
539 xMtfFastPropertySet->setFastPropertyValue( 0, uno::Any( reinterpret_cast<sal_Int64>( this ) ) );
541 xMtfRenderer->draw( rDestSize.Width(), rDestSize.Height() );
543 uno::Reference< beans::XFastPropertySet > xFastPropertySet( xBitmapCanvas, uno::UNO_QUERY );
544 if( xFastPropertySet.get() ) {
545 // 0 means get BitmapEx
546 uno::Any aAny = xFastPropertySet->getFastPropertyValue( 0 );
547 BitmapEx* pBitmapEx = (BitmapEx*) *reinterpret_cast<const sal_Int64*>(aAny.getValue());
548 if( pBitmapEx ) {
549 pOut->DrawBitmapEx( rPos, *pBitmapEx );
550 delete pBitmapEx;
551 return true;
555 SalBitmap* pSalBmp = ImplGetSVData()->mpDefInst->CreateSalBitmap();
556 SalBitmap* pSalMask = ImplGetSVData()->mpDefInst->CreateSalBitmap();
558 if( pSalBmp->Create( xBitmapCanvas, aSize ) && pSalMask->Create( xBitmapCanvas, aSize, true ) ) {
559 Bitmap aBitmap( pSalBmp );
560 Bitmap aMask( pSalMask );
561 AlphaMask aAlphaMask( aMask );
562 BitmapEx aBitmapEx( aBitmap, aAlphaMask );
563 pOut->DrawBitmapEx( rPos, aBitmapEx );
564 return true;
567 delete pSalBmp;
568 delete pSalMask;
574 return false;
577 // ------------------------------------------------------------------------
579 void GDIMetaFile::ImplDelegate2PluggableRenderer( const MetaCommentAction* pAct, OutputDevice* pOut )
581 OSL_ASSERT( pAct->GetComment().Equals("DELEGATE_PLUGGABLE_RENDERER") );
583 // read payload - string of service name, followed by raw render input
584 const BYTE* pData = pAct->GetData();
585 const BYTE* const pEndData = pData + pAct->GetDataSize();
586 if( !pData )
587 return;
589 ::rtl::OUStringBuffer aBuffer;
590 while( pData<pEndData && *pData )
591 aBuffer.append(static_cast<sal_Unicode>(*pData++));
592 const ::rtl::OUString aRendererServiceName=aBuffer.makeStringAndClear();
593 ++pData;
595 while( pData<pEndData && *pData )
596 aBuffer.append(static_cast<sal_Unicode>(*pData++));
597 const ::rtl::OUString aGraphicServiceName=aBuffer.makeStringAndClear();
598 ++pData;
600 uno::Reference< lang::XMultiServiceFactory > xFactory = vcl::unohelper::GetMultiServiceFactory();
601 if( pData<pEndData && xFactory.is() )
605 // instantiate render service
606 uno::Sequence<uno::Any> aRendererArgs(1);
607 aRendererArgs[0] = makeAny(uno::Reference<awt::XGraphics>(pOut->CreateUnoGraphics()));
608 uno::Reference<graphic::XGraphicRenderer> xRenderer(
609 xFactory->createInstanceWithArguments(
610 aRendererServiceName,
611 aRendererArgs),
612 uno::UNO_QUERY );
614 // instantiate graphic service
615 uno::Reference<graphic::XGraphic> xGraphic(
616 xFactory->createInstance(
617 aGraphicServiceName),
618 uno::UNO_QUERY );
620 uno::Reference<lang::XInitialization> xInit(
621 xGraphic, uno::UNO_QUERY);
623 if(xGraphic.is() && xRenderer.is() && xInit.is())
625 // delay intialization of XGraphic, to only expose
626 // XGraphic-generating services to arbitrary binary data
627 uno::Sequence< sal_Int8 > aSeq(
628 (sal_Int8*)&pData, pEndData-pData );
629 uno::Sequence<uno::Any> aGraphicsArgs(1);
630 aGraphicsArgs[0] = makeAny(aSeq);
631 xInit->initialize(aGraphicsArgs);
633 xRenderer->render(xGraphic);
636 catch( uno::RuntimeException& )
638 // runtime errors are fatal
639 throw;
641 catch( uno::Exception& )
643 // ignore errors, no way of reporting them here
648 // ------------------------------------------------------------------------
650 void GDIMetaFile::Play( OutputDevice* pOut, const Point& rPos,
651 const Size& rSize, ULONG nPos )
653 Region aDrawClipRegion;
654 MapMode aDrawMap( GetPrefMapMode() );
655 Size aDestSize( pOut->LogicToPixel( rSize ) );
657 if( aDestSize.Width() && aDestSize.Height() )
659 GDIMetaFile* pMtf = pOut->GetConnectMetaFile();
661 if( bUseCanvas && !pMtf && ImplPlayWithRenderer( pOut, rPos, aDestSize ) )
662 return;
664 Size aTmpPrefSize( pOut->LogicToPixel( GetPrefSize(), aDrawMap ) );
666 if( !aTmpPrefSize.Width() )
667 aTmpPrefSize.Width() = aDestSize.Width();
669 if( !aTmpPrefSize.Height() )
670 aTmpPrefSize.Height() = aDestSize.Height();
672 Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() );
673 Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() );
675 aScaleX *= aDrawMap.GetScaleX(); aDrawMap.SetScaleX( aScaleX );
676 aScaleY *= aDrawMap.GetScaleY(); aDrawMap.SetScaleY( aScaleY );
678 // #i47260# Convert logical output position to offset within
679 // the metafile's mapmode. Therefore, disable pixel offset on
680 // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
681 // different mapmode (the one currently set on pOut, that is)
682 // - thus, aDrawMap's origin would generally be wrong. And
683 // even _if_ aDrawMap is similar to pOutDev's current mapmode,
684 // it's _still_ undesirable to have pixel offset unequal zero,
685 // because one would still get round-off errors (the
686 // round-trip error for LogicToPixel( PixelToLogic() ) was the
687 // reason for having pixel offset in the first place).
688 const Size& rOldOffset( pOut->GetPixelOffset() );
689 const Size aEmptySize;
690 pOut->SetPixelOffset( aEmptySize );
691 aDrawMap.SetOrigin( pOut->PixelToLogic( pOut->LogicToPixel( rPos ), aDrawMap ) );
692 pOut->SetPixelOffset( rOldOffset );
694 pOut->Push();
696 if ( pMtf && pMtf->IsRecord() && ( pOut->GetOutDevType() != OUTDEV_PRINTER ) )
697 pOut->SetRelativeMapMode( aDrawMap );
698 else
699 pOut->SetMapMode( aDrawMap );
701 // #i23407# Set backwards-compatible text language and layout mode
702 // This is necessary, since old metafiles don't even know of these
703 // recent add-ons. Newer metafiles must of course explicitely set
704 // those states.
705 pOut->SetLayoutMode( 0 );
706 pOut->SetDigitLanguage( 0 );
708 Play( pOut, nPos );
710 pOut->Pop();
714 // ------------------------------------------------------------------------
716 void GDIMetaFile::Pause( BOOL _bPause )
718 if( bRecord )
720 if( _bPause )
722 if( !bPause )
723 Linker( pOutDev, FALSE );
725 else
727 if( bPause )
728 Linker( pOutDev, TRUE );
731 bPause = _bPause;
735 // ------------------------------------------------------------------------
737 void GDIMetaFile::Stop()
739 if( bRecord )
741 bRecord = FALSE;
743 if( !bPause )
744 Linker( pOutDev, FALSE );
745 else
746 bPause = FALSE;
750 // ------------------------------------------------------------------------
752 void GDIMetaFile::WindStart()
754 if( !bRecord )
755 First();
758 // ------------------------------------------------------------------------
760 void GDIMetaFile::WindEnd()
762 if( !bRecord )
763 Last();
766 // ------------------------------------------------------------------------
768 void GDIMetaFile::Wind( ULONG nActionPos )
770 if( !bRecord )
771 Seek( nActionPos );
774 // ------------------------------------------------------------------------
776 void GDIMetaFile::WindPrev()
778 if( !bRecord )
779 Prev();
782 // ------------------------------------------------------------------------
784 void GDIMetaFile::WindNext()
786 if( !bRecord )
787 Next();
790 // ------------------------------------------------------------------------
792 void GDIMetaFile::AddAction( MetaAction* pAction )
794 Insert( pAction, LIST_APPEND );
796 if( pPrev )
798 pAction->Duplicate();
799 pPrev->AddAction( pAction );
803 // ------------------------------------------------------------------------
805 void GDIMetaFile::AddAction( MetaAction* pAction, ULONG nPos )
807 Insert( pAction, nPos );
809 if( pPrev )
811 pAction->Duplicate();
812 pPrev->AddAction( pAction, nPos );
816 // ------------------------------------------------------------------------
818 // @since #110496#
819 void GDIMetaFile::RemoveAction( ULONG nPos )
821 Remove( nPos );
823 if( pPrev )
824 pPrev->RemoveAction( nPos );
827 // ------------------------------------------------------------------------
829 MetaAction* GDIMetaFile::CopyAction( ULONG nPos ) const
831 return ( (MetaAction*) GetObject( nPos ) )->Clone();
834 // ------------------------------------------------------------------------
836 ULONG GDIMetaFile::GetActionPos( const String& rLabel )
838 ImpLabel* pLabel = NULL;
840 if( pLabelList )
841 pLabel = pLabelList->ImplGetLabel( pLabelList->ImplGetLabelPos( rLabel ) );
842 else
843 pLabel = NULL;
845 return( pLabel ? pLabel->nActionPos : METAFILE_LABEL_NOTFOUND );
848 // ------------------------------------------------------------------------
850 BOOL GDIMetaFile::InsertLabel( const String& rLabel, ULONG nActionPos )
852 BOOL bRet = FALSE;
854 if( !pLabelList )
855 pLabelList = new ImpLabelList;
857 if( pLabelList->ImplGetLabelPos( rLabel ) == METAFILE_LABEL_NOTFOUND )
859 pLabelList->ImplInsert( new ImpLabel( rLabel, nActionPos ) );
860 bRet = TRUE;
863 return bRet;
866 // ------------------------------------------------------------------------
868 void GDIMetaFile::RemoveLabel( const String& rLabel )
870 if( pLabelList )
872 const ULONG nLabelPos = pLabelList->ImplGetLabelPos( rLabel );
874 if( nLabelPos != METAFILE_LABEL_NOTFOUND )
875 delete pLabelList->ImplRemove( nLabelPos );
879 // ------------------------------------------------------------------------
881 void GDIMetaFile::RenameLabel( const String& rLabel, const String& rNewLabel )
883 if( pLabelList )
885 const ULONG nLabelPos = pLabelList->ImplGetLabelPos( rLabel );
887 if ( nLabelPos != METAFILE_LABEL_NOTFOUND )
888 pLabelList->ImplGetLabel( nLabelPos )->aLabelName = rNewLabel;
892 // ------------------------------------------------------------------------
894 ULONG GDIMetaFile::GetLabelCount() const
896 return( pLabelList ? pLabelList->ImplCount() : 0UL );
899 // ------------------------------------------------------------------------
901 String GDIMetaFile::GetLabel( ULONG nLabel )
903 String aString;
905 if( pLabelList )
907 const ImpLabel* pLabel = pLabelList->ImplGetLabel( nLabel );
909 if( pLabel )
910 aString = pLabel->aLabelName;
913 return aString;
916 // ------------------------------------------------------------------------
918 BOOL GDIMetaFile::SaveStatus()
920 if ( bRecord )
922 if ( bPause )
923 Linker( pOutDev, TRUE );
925 AddAction( new MetaLineColorAction( pOutDev->GetLineColor(),
926 pOutDev->IsLineColor() ) );
927 AddAction( new MetaFillColorAction( pOutDev->GetFillColor(),
928 pOutDev->IsFillColor() ) );
929 AddAction( new MetaFontAction( pOutDev->GetFont() ) );
930 AddAction( new MetaTextColorAction( pOutDev->GetTextColor() ) );
931 AddAction( new MetaTextFillColorAction( pOutDev->GetTextFillColor(),
932 pOutDev->IsTextFillColor() ) );
933 AddAction( new MetaTextLineColorAction( pOutDev->GetTextLineColor(),
934 pOutDev->IsTextLineColor() ) );
935 AddAction( new MetaOverlineColorAction( pOutDev->GetOverlineColor(),
936 pOutDev->IsOverlineColor() ) );
937 AddAction( new MetaTextAlignAction( pOutDev->GetTextAlign() ) );
938 AddAction( new MetaRasterOpAction( pOutDev->GetRasterOp() ) );
939 AddAction( new MetaMapModeAction( pOutDev->GetMapMode() ) );
940 AddAction( new MetaClipRegionAction( pOutDev->GetClipRegion(),
941 pOutDev->IsClipRegion() ) );
943 if ( bPause )
944 Linker( pOutDev, FALSE );
946 return TRUE;
948 else
949 return FALSE;
952 // ------------------------------------------------------------------------
954 BOOL GDIMetaFile::Mirror( ULONG nMirrorFlags )
956 const Size aOldPrefSize( GetPrefSize() );
957 long nMoveX, nMoveY;
958 double fScaleX, fScaleY;
959 BOOL bRet;
961 if( nMirrorFlags & MTF_MIRROR_HORZ )
962 nMoveX = VOS_ABS( aOldPrefSize.Width() ) - 1, fScaleX = -1.0;
963 else
964 nMoveX = 0, fScaleX = 1.0;
966 if( nMirrorFlags & MTF_MIRROR_VERT )
967 nMoveY = VOS_ABS( aOldPrefSize.Height() ) - 1, fScaleY = -1.0;
968 else
969 nMoveY = 0, fScaleY = 1.0;
971 if( ( fScaleX != 1.0 ) || ( fScaleY != 1.0 ) )
973 Scale( fScaleX, fScaleY );
974 Move( nMoveX, nMoveY );
975 SetPrefSize( aOldPrefSize );
976 bRet = TRUE;
978 else
979 bRet = FALSE;
981 return bRet;
984 // ------------------------------------------------------------------------
986 void GDIMetaFile::Move( long nX, long nY )
988 const Size aBaseOffset( nX, nY );
989 Size aOffset( aBaseOffset );
990 VirtualDevice aMapVDev;
992 aMapVDev.EnableOutput( FALSE );
993 aMapVDev.SetMapMode( GetPrefMapMode() );
995 for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() )
997 const long nType = pAct->GetType();
998 MetaAction* pModAct;
1000 if( pAct->GetRefCount() > 1 )
1002 Replace( pModAct = pAct->Clone(), GetCurPos() );
1003 pAct->Delete();
1005 else
1006 pModAct = pAct;
1008 if( ( META_MAPMODE_ACTION == nType ) ||
1009 ( META_PUSH_ACTION == nType ) ||
1010 ( META_POP_ACTION == nType ) )
1012 pModAct->Execute( &aMapVDev );
1013 aOffset = aMapVDev.LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev.GetMapMode() );
1016 pModAct->Move( aOffset.Width(), aOffset.Height() );
1020 // ------------------------------------------------------------------------
1022 void GDIMetaFile::Scale( double fScaleX, double fScaleY )
1024 for( MetaAction* pAct = (MetaAction*) First(); pAct; pAct = (MetaAction*) Next() )
1026 MetaAction* pModAct;
1028 if( pAct->GetRefCount() > 1 )
1030 Replace( pModAct = pAct->Clone(), GetCurPos() );
1031 pAct->Delete();
1033 else
1034 pModAct = pAct;
1036 pModAct->Scale( fScaleX, fScaleY );
1039 aPrefSize.Width() = FRound( aPrefSize.Width() * fScaleX );
1040 aPrefSize.Height() = FRound( aPrefSize.Height() * fScaleY );
1043 // ------------------------------------------------------------------------
1045 void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY )
1047 Scale( (double) rScaleX, (double) rScaleY );
1050 // ------------------------------------------------------------------------
1052 Point GDIMetaFile::ImplGetRotatedPoint( const Point& rPt, const Point& rRotatePt,
1053 const Size& rOffset, double fSin, double fCos )
1055 const long nX = rPt.X() - rRotatePt.X();
1056 const long nY = rPt.Y() - rRotatePt.Y();
1058 return Point( FRound( fCos * nX + fSin * nY ) + rRotatePt.X() + rOffset.Width(),
1059 -FRound( fSin * nX - fCos * nY ) + rRotatePt.Y() + rOffset.Height() );
1062 // ------------------------------------------------------------------------
1064 Polygon GDIMetaFile::ImplGetRotatedPolygon( const Polygon& rPoly, const Point& rRotatePt,
1065 const Size& rOffset, double fSin, double fCos )
1067 Polygon aRet( rPoly );
1069 aRet.Rotate( rRotatePt, fSin, fCos );
1070 aRet.Move( rOffset.Width(), rOffset.Height() );
1072 return aRet;
1075 // ------------------------------------------------------------------------
1077 PolyPolygon GDIMetaFile::ImplGetRotatedPolyPolygon( const PolyPolygon& rPolyPoly, const Point& rRotatePt,
1078 const Size& rOffset, double fSin, double fCos )
1080 PolyPolygon aRet( rPolyPoly );
1082 aRet.Rotate( rRotatePt, fSin, fCos );
1083 aRet.Move( rOffset.Width(), rOffset.Height() );
1085 return aRet;
1088 // ------------------------------------------------------------------------
1090 void GDIMetaFile::ImplAddGradientEx( GDIMetaFile& rMtf,
1091 const OutputDevice& rMapDev,
1092 const PolyPolygon& rPolyPoly,
1093 const Gradient& rGrad )
1095 // #105055# Generate comment, GradientEx and Gradient actions
1096 // (within DrawGradient)
1097 VirtualDevice aVDev( rMapDev, 0 );
1098 aVDev.EnableOutput( FALSE );
1099 GDIMetaFile aGradMtf;
1101 aGradMtf.Record( &aVDev );
1102 aVDev.DrawGradient( rPolyPoly, rGrad );
1103 aGradMtf.Stop();
1105 int i, nAct( aGradMtf.GetActionCount() );
1106 for( i=0; i<nAct; ++i )
1108 MetaAction* pMetaAct = aGradMtf.GetAction(i);
1109 pMetaAct->Duplicate();
1110 rMtf.AddAction( pMetaAct );
1114 // ------------------------------------------------------------------------
1116 void GDIMetaFile::Rotate( long nAngle10 )
1118 nAngle10 %= 3600L;
1119 nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
1121 if( nAngle10 )
1123 GDIMetaFile aMtf;
1124 VirtualDevice aMapVDev;
1125 const double fAngle = F_PI1800 * nAngle10;
1126 const double fSin = sin( fAngle );
1127 const double fCos = cos( fAngle );
1128 Rectangle aRect=Rectangle( Point(), GetPrefSize() );
1129 Polygon aPoly( aRect );
1131 aPoly.Rotate( Point(), fSin, fCos );
1133 aMapVDev.EnableOutput( FALSE );
1134 aMapVDev.SetMapMode( GetPrefMapMode() );
1136 const Rectangle aNewBound( aPoly.GetBoundRect() );
1138 const Point aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
1139 const Size aOffset( -aNewBound.Left(), -aNewBound.Top() );
1141 Point aRotAnchor( aOrigin );
1142 Size aRotOffset( aOffset );
1144 for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() )
1146 const USHORT nActionType = pAction->GetType();
1148 switch( nActionType )
1150 case( META_PIXEL_ACTION ):
1152 MetaPixelAction* pAct = (MetaPixelAction*) pAction;
1153 aMtf.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1154 pAct->GetColor() ) );
1156 break;
1158 case( META_POINT_ACTION ):
1160 MetaPointAction* pAct = (MetaPointAction*) pAction;
1161 aMtf.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1163 break;
1165 case( META_LINE_ACTION ):
1167 MetaLineAction* pAct = (MetaLineAction*) pAction;
1168 aMtf.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1169 ImplGetRotatedPoint( pAct->GetEndPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1170 pAct->GetLineInfo() ) );
1172 break;
1174 case( META_RECT_ACTION ):
1176 MetaRectAction* pAct = (MetaRectAction*) pAction;
1177 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1179 break;
1181 case( META_ROUNDRECT_ACTION ):
1183 MetaRoundRectAction* pAct = (MetaRoundRectAction*) pAction;
1184 const Polygon aRoundRectPoly( pAct->GetRect(), pAct->GetHorzRound(), pAct->GetVertRound() );
1186 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1188 break;
1190 case( META_ELLIPSE_ACTION ):
1192 MetaEllipseAction* pAct = (MetaEllipseAction*) pAction;
1193 const Polygon aEllipsePoly( pAct->GetRect().Center(), pAct->GetRect().GetWidth() >> 1, pAct->GetRect().GetHeight() >> 1 );
1195 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1197 break;
1199 case( META_ARC_ACTION ):
1201 MetaArcAction* pAct = (MetaArcAction*) pAction;
1202 const Polygon aArcPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_ARC );
1204 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1206 break;
1208 case( META_PIE_ACTION ):
1210 MetaPieAction* pAct = (MetaPieAction*) pAction;
1211 const Polygon aPiePoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_PIE );
1213 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1215 break;
1217 case( META_CHORD_ACTION ):
1219 MetaChordAction* pAct = (MetaChordAction*) pAction;
1220 const Polygon aChordPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_CHORD );
1222 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1224 break;
1226 case( META_POLYLINE_ACTION ):
1228 MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction;
1229 aMtf.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->GetLineInfo() ) );
1231 break;
1233 case( META_POLYGON_ACTION ):
1235 MetaPolygonAction* pAct = (MetaPolygonAction*) pAction;
1236 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1238 break;
1240 case( META_POLYPOLYGON_ACTION ):
1242 MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction;
1243 aMtf.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1245 break;
1247 case( META_TEXT_ACTION ):
1249 MetaTextAction* pAct = (MetaTextAction*) pAction;
1250 aMtf.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1251 pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
1253 break;
1255 case( META_TEXTARRAY_ACTION ):
1257 MetaTextArrayAction* pAct = (MetaTextArrayAction*) pAction;
1258 aMtf.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1259 pAct->GetText(), pAct->GetDXArray(), pAct->GetIndex(), pAct->GetLen() ) );
1261 break;
1263 case( META_STRETCHTEXT_ACTION ):
1265 MetaStretchTextAction* pAct = (MetaStretchTextAction*) pAction;
1266 aMtf.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1267 pAct->GetWidth(), pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
1269 break;
1271 case( META_TEXTLINE_ACTION ):
1273 MetaTextLineAction* pAct = (MetaTextLineAction*) pAction;
1274 aMtf.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1275 pAct->GetWidth(), pAct->GetStrikeout(), pAct->GetUnderline(), pAct->GetOverline() ) );
1277 break;
1279 case( META_BMPSCALE_ACTION ):
1281 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
1282 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1283 Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1284 BitmapEx aBmpEx( pAct->GetBitmap() );
1286 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1287 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(),
1288 aBmpEx ) );
1290 break;
1292 case( META_BMPSCALEPART_ACTION ):
1294 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
1295 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1296 Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1297 BitmapEx aBmpEx( pAct->GetBitmap() );
1299 aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1300 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1302 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1304 break;
1306 case( META_BMPEXSCALE_ACTION ):
1308 MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
1309 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1310 Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1311 BitmapEx aBmpEx( pAct->GetBitmapEx() );
1313 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1315 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1317 break;
1319 case( META_BMPEXSCALEPART_ACTION ):
1321 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
1322 Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1323 Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1324 BitmapEx aBmpEx( pAct->GetBitmapEx() );
1326 aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1327 aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1329 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1331 break;
1333 case( META_GRADIENT_ACTION ):
1335 MetaGradientAction* pAct = (MetaGradientAction*) pAction;
1337 ImplAddGradientEx( aMtf, aMapVDev,
1338 ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ),
1339 pAct->GetGradient() );
1341 break;
1343 case( META_GRADIENTEX_ACTION ):
1345 MetaGradientExAction* pAct = (MetaGradientExAction*) pAction;
1346 aMtf.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1347 pAct->GetGradient() ) );
1349 break;
1351 // #105055# Handle gradientex comment block correctly
1352 case( META_COMMENT_ACTION ):
1354 MetaCommentAction* pCommentAct = (MetaCommentAction*) pAction;
1355 if( pCommentAct->GetComment().Equals( "XGRAD_SEQ_BEGIN" ) )
1357 int nBeginComments( 1 );
1358 pAction = (MetaAction*) Next();
1360 // skip everything, except gradientex action
1361 while( pAction )
1363 const USHORT nType = pAction->GetType();
1365 if( META_GRADIENTEX_ACTION == nType )
1367 // Add rotated gradientex
1368 MetaGradientExAction* pAct = (MetaGradientExAction*) pAction;
1369 ImplAddGradientEx( aMtf, aMapVDev,
1370 ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1371 pAct->GetGradient() );
1373 else if( META_COMMENT_ACTION == nType)
1375 MetaCommentAction* pAct = (MetaCommentAction*) pAction;
1376 if( pAct->GetComment().Equals( "XGRAD_SEQ_END" ) )
1378 // handle nested blocks
1379 --nBeginComments;
1381 // gradientex comment block: end reached, done.
1382 if( !nBeginComments )
1383 break;
1385 else if( pAct->GetComment().Equals( "XGRAD_SEQ_BEGIN" ) )
1387 // handle nested blocks
1388 ++nBeginComments;
1393 pAction = (MetaAction*) Next();
1396 else
1398 sal_Bool bPathStroke = pCommentAct->GetComment().Equals( "XPATHSTROKE_SEQ_BEGIN" );
1399 if ( bPathStroke || pCommentAct->GetComment().Equals( "XPATHFILL_SEQ_BEGIN" ) )
1401 if ( pCommentAct->GetDataSize() )
1403 SvMemoryStream aMemStm( (void*)pCommentAct->GetData(), pCommentAct->GetDataSize(), STREAM_READ );
1404 SvMemoryStream aDest;
1405 if ( bPathStroke )
1407 SvtGraphicStroke aStroke;
1408 aMemStm >> aStroke;
1409 Polygon aPath;
1410 aStroke.getPath( aPath );
1411 aStroke.setPath( ImplGetRotatedPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1412 aDest << aStroke;
1413 aMtf.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1414 static_cast<const BYTE*>( aDest.GetData()), aDest.Tell() ) );
1416 else
1418 SvtGraphicFill aFill;
1419 aMemStm >> aFill;
1420 PolyPolygon aPath;
1421 aFill.getPath( aPath );
1422 aFill.setPath( ImplGetRotatedPolyPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1423 aDest << aFill;
1424 aMtf.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1425 static_cast<const BYTE*>( aDest.GetData()), aDest.Tell() ) );
1429 else if ( pCommentAct->GetComment().Equals( "XPATHSTROKE_SEQ_END" )
1430 || pCommentAct->GetComment().Equals( "XPATHFILL_SEQ_END" ) )
1432 pAction->Execute( &aMapVDev );
1433 pAction->Duplicate();
1434 aMtf.AddAction( pAction );
1438 break;
1440 case( META_HATCH_ACTION ):
1442 MetaHatchAction* pAct = (MetaHatchAction*) pAction;
1443 Hatch aHatch( pAct->GetHatch() );
1445 aHatch.SetAngle( aHatch.GetAngle() + (USHORT) nAngle10 );
1446 aMtf.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1447 aHatch ) );
1449 break;
1451 case( META_TRANSPARENT_ACTION ):
1453 MetaTransparentAction* pAct = (MetaTransparentAction*) pAction;
1454 aMtf.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1455 pAct->GetTransparence() ) );
1457 break;
1459 case( META_FLOATTRANSPARENT_ACTION ):
1461 MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction;
1462 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
1463 Polygon aMtfPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1464 Rectangle aMtfRect( aMtfPoly.GetBoundRect() );
1466 aTransMtf.Rotate( nAngle10 );
1467 aMtf.AddAction( new MetaFloatTransparentAction( aTransMtf, aMtfRect.TopLeft(), aMtfRect.GetSize(),
1468 pAct->GetGradient() ) );
1470 break;
1472 case( META_EPS_ACTION ):
1474 MetaEPSAction* pAct = (MetaEPSAction*) pAction;
1475 GDIMetaFile aEPSMtf( pAct->GetSubstitute() );
1476 Polygon aEPSPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1477 Rectangle aEPSRect( aEPSPoly.GetBoundRect() );
1479 aEPSMtf.Rotate( nAngle10 );
1480 aMtf.AddAction( new MetaEPSAction( aEPSRect.TopLeft(), aEPSRect.GetSize(),
1481 pAct->GetLink(), aEPSMtf ) );
1483 break;
1485 case( META_CLIPREGION_ACTION ):
1487 MetaClipRegionAction* pAct = (MetaClipRegionAction*) pAction;
1489 if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygon() )
1490 aMtf.AddAction( new MetaClipRegionAction( Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), TRUE ) );
1491 else
1493 pAction->Duplicate();
1494 aMtf.AddAction( pAction );
1497 break;
1499 case( META_ISECTRECTCLIPREGION_ACTION ):
1501 MetaISectRectClipRegionAction* pAct = (MetaISectRectClipRegionAction*) pAction;
1502 aMtf.AddAction( new MetaISectRegionClipRegionAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1504 break;
1506 case( META_ISECTREGIONCLIPREGION_ACTION ):
1508 MetaISectRegionClipRegionAction* pAct = (MetaISectRegionClipRegionAction*) pAction;
1509 const Region& rRegion = pAct->GetRegion();
1511 if( rRegion.HasPolyPolygon() )
1512 aMtf.AddAction( new MetaISectRegionClipRegionAction( Region( ImplGetRotatedPolyPolygon( rRegion.GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) );
1513 else
1515 pAction->Duplicate();
1516 aMtf.AddAction( pAction );
1519 break;
1521 case( META_REFPOINT_ACTION ):
1523 MetaRefPointAction* pAct = (MetaRefPointAction*) pAction;
1524 aMtf.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct->GetRefPoint(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->IsSetting() ) );
1526 break;
1528 case( META_FONT_ACTION ):
1530 MetaFontAction* pAct = (MetaFontAction*) pAction;
1531 Font aFont( pAct->GetFont() );
1533 aFont.SetOrientation( aFont.GetOrientation() + (USHORT) nAngle10 );
1534 aMtf.AddAction( new MetaFontAction( aFont ) );
1536 break;
1538 case( META_BMP_ACTION ):
1539 case( META_BMPEX_ACTION ):
1540 case( META_MASK_ACTION ):
1541 case( META_MASKSCALE_ACTION ):
1542 case( META_MASKSCALEPART_ACTION ):
1543 case( META_WALLPAPER_ACTION ):
1544 case( META_TEXTRECT_ACTION ):
1545 case( META_MOVECLIPREGION_ACTION ):
1547 DBG_ERROR( "GDIMetaFile::Rotate(): unsupported action" );
1549 break;
1551 default:
1553 pAction->Execute( &aMapVDev );
1554 pAction->Duplicate();
1555 aMtf.AddAction( pAction );
1557 // update rotation point and offset, if necessary
1558 if( ( META_MAPMODE_ACTION == nActionType ) ||
1559 ( META_PUSH_ACTION == nActionType ) ||
1560 ( META_POP_ACTION == nActionType ) )
1562 aRotAnchor = aMapVDev.LogicToLogic( aOrigin, aPrefMapMode, aMapVDev.GetMapMode() );
1563 aRotOffset = aMapVDev.LogicToLogic( aOffset, aPrefMapMode, aMapVDev.GetMapMode() );
1566 break;
1570 aMtf.aPrefMapMode = aPrefMapMode;
1571 aMtf.aPrefSize = aNewBound.GetSize();
1573 *this = aMtf;
1577 // ------------------------------------------------------------------------
1579 static void ImplActionBounds( Rectangle& o_rOutBounds,
1580 const Rectangle& i_rInBounds,
1581 const std::vector<Rectangle>& i_rClipStack )
1583 Rectangle aBounds( i_rInBounds );
1584 if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() )
1585 aBounds.Intersection( i_rClipStack.back() );
1586 if( ! aBounds.IsEmpty() )
1588 if( ! o_rOutBounds.IsEmpty() )
1589 o_rOutBounds.Union( aBounds );
1590 else
1591 o_rOutBounds = aBounds;
1595 Rectangle GDIMetaFile::GetBoundRect( OutputDevice& i_rReference )
1597 GDIMetaFile aMtf;
1598 VirtualDevice aMapVDev( i_rReference );
1600 aMapVDev.EnableOutput( FALSE );
1601 aMapVDev.SetMapMode( GetPrefMapMode() );
1603 std::vector<Rectangle> aClipStack( 1, Rectangle() );
1604 std::vector<USHORT> aPushFlagStack;
1606 Rectangle aBound;
1608 for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() )
1610 const USHORT nActionType = pAction->GetType();
1612 switch( nActionType )
1614 case( META_PIXEL_ACTION ):
1616 MetaPixelAction* pAct = (MetaPixelAction*) pAction;
1617 ImplActionBounds( aBound,
1618 Rectangle( aMapVDev.LogicToLogic( pAct->GetPoint(), aMapVDev.GetMapMode(), GetPrefMapMode() ),
1619 aMapVDev.PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1620 aClipStack );
1622 break;
1624 case( META_POINT_ACTION ):
1626 MetaPointAction* pAct = (MetaPointAction*) pAction;
1627 ImplActionBounds( aBound,
1628 Rectangle( aMapVDev.LogicToLogic( pAct->GetPoint(), aMapVDev.GetMapMode(), GetPrefMapMode() ),
1629 aMapVDev.PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1630 aClipStack );
1632 break;
1634 case( META_LINE_ACTION ):
1636 MetaLineAction* pAct = (MetaLineAction*) pAction;
1637 Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() );
1638 Rectangle aRect( aP1, aP2 );
1639 aRect.Justify();
1640 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1642 break;
1644 case( META_RECT_ACTION ):
1646 MetaRectAction* pAct = (MetaRectAction*) pAction;
1647 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1649 break;
1651 case( META_ROUNDRECT_ACTION ):
1653 MetaRoundRectAction* pAct = (MetaRoundRectAction*) pAction;
1654 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1656 break;
1658 case( META_ELLIPSE_ACTION ):
1660 MetaEllipseAction* pAct = (MetaEllipseAction*) pAction;
1661 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1663 break;
1665 case( META_ARC_ACTION ):
1667 MetaArcAction* pAct = (MetaArcAction*) pAction;
1668 // FIXME: this is imprecise
1669 // e.g. for small arcs the whole rectangle is WAY too large
1670 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1672 break;
1674 case( META_PIE_ACTION ):
1676 MetaPieAction* pAct = (MetaPieAction*) pAction;
1677 // FIXME: this is imprecise
1678 // e.g. for small arcs the whole rectangle is WAY too large
1679 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1681 break;
1683 case( META_CHORD_ACTION ):
1685 MetaChordAction* pAct = (MetaChordAction*) pAction;
1686 // FIXME: this is imprecise
1687 // e.g. for small arcs the whole rectangle is WAY too large
1688 ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1690 break;
1692 case( META_POLYLINE_ACTION ):
1694 MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction;
1695 Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1696 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1698 break;
1700 case( META_POLYGON_ACTION ):
1702 MetaPolygonAction* pAct = (MetaPolygonAction*) pAction;
1703 Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1704 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1706 break;
1708 case( META_POLYPOLYGON_ACTION ):
1710 MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction;
1711 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1712 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1714 break;
1716 case( META_TEXT_ACTION ):
1718 MetaTextAction* pAct = (MetaTextAction*) pAction;
1719 Rectangle aRect;
1720 // hdu said base = index
1721 aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() );
1722 Point aPt( pAct->GetPoint() );
1723 aRect.Move( aPt.X(), aPt.Y() );
1724 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1726 break;
1728 case( META_TEXTARRAY_ACTION ):
1730 MetaTextArrayAction* pAct = (MetaTextArrayAction*) pAction;
1731 Rectangle aRect;
1732 // hdu said base = index
1733 aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1734 0, pAct->GetDXArray() );
1735 Point aPt( pAct->GetPoint() );
1736 aRect.Move( aPt.X(), aPt.Y() );
1737 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1739 break;
1741 case( META_STRETCHTEXT_ACTION ):
1743 MetaStretchTextAction* pAct = (MetaStretchTextAction*) pAction;
1744 Rectangle aRect;
1745 // hdu said base = index
1746 aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1747 pAct->GetWidth(), NULL );
1748 Point aPt( pAct->GetPoint() );
1749 aRect.Move( aPt.X(), aPt.Y() );
1750 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1752 break;
1754 case( META_TEXTLINE_ACTION ):
1756 MetaTextLineAction* pAct = (MetaTextLineAction*) pAction;
1757 // measure a test string to get ascend and descent right
1758 static const sal_Unicode pStr[] = { 0xc4, 0x67, 0 };
1759 String aStr( pStr );
1761 Rectangle aRect;
1762 aMapVDev.GetTextBoundRect( aRect, aStr, 0, 0, aStr.Len(), 0, NULL );
1763 Point aPt( pAct->GetStartPoint() );
1764 aRect.Move( aPt.X(), aPt.Y() );
1765 aRect.Right() = aRect.Left() + pAct->GetWidth();
1766 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1768 break;
1770 case( META_BMPSCALE_ACTION ):
1772 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
1773 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1774 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1776 break;
1778 case( META_BMPSCALEPART_ACTION ):
1780 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
1781 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1782 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1784 break;
1786 case( META_BMPEXSCALE_ACTION ):
1788 MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
1789 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1790 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1792 break;
1794 case( META_BMPEXSCALEPART_ACTION ):
1796 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
1797 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1798 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1800 break;
1802 case( META_GRADIENT_ACTION ):
1804 MetaGradientAction* pAct = (MetaGradientAction*) pAction;
1805 Rectangle aRect( pAct->GetRect() );
1806 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1808 break;
1810 case( META_GRADIENTEX_ACTION ):
1812 MetaGradientExAction* pAct = (MetaGradientExAction*) pAction;
1813 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1814 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1816 break;
1818 case( META_COMMENT_ACTION ):
1820 // nothing to do
1822 break;
1824 case( META_HATCH_ACTION ):
1826 MetaHatchAction* pAct = (MetaHatchAction*) pAction;
1827 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1828 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1830 break;
1832 case( META_TRANSPARENT_ACTION ):
1834 MetaTransparentAction* pAct = (MetaTransparentAction*) pAction;
1835 Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1836 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1838 break;
1840 case( META_FLOATTRANSPARENT_ACTION ):
1842 MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction;
1843 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
1844 // get the bound rect of the contained metafile
1845 Rectangle aRect( aTransMtf.GetBoundRect( i_rReference ) );
1846 // scale the rect now on the assumption that the correct top left of the metafile
1847 // (not its bounds !) is (0,0)
1848 Size aPSize( aTransMtf.GetPrefSize() );
1849 aPSize = aMapVDev.LogicToLogic( aPSize, aTransMtf.GetPrefMapMode(), aMapVDev.GetMapMode() );
1850 Size aActSize( pAct->GetSize() );
1851 double fX = double(aActSize.Width())/double(aPSize.Width());
1852 double fY = double(aActSize.Height())/double(aPSize.Height());
1853 aRect.Left() = long(double(aRect.Left())*fX);
1854 aRect.Right() = long(double(aRect.Right())*fX);
1855 aRect.Top() = long(double(aRect.Top())*fY);
1856 aRect.Bottom() = long(double(aRect.Bottom())*fY);
1858 // transform the rect to current VDev state
1859 aRect = aMapVDev.LogicToLogic( aRect, aTransMtf.GetPrefMapMode(), aMapVDev.GetMapMode() );
1861 ImplActionBounds( aBound, aRect, aClipStack );
1863 break;
1865 case( META_EPS_ACTION ):
1867 MetaEPSAction* pAct = (MetaEPSAction*) pAction;
1868 Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1869 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1871 break;
1873 case( META_CLIPREGION_ACTION ):
1875 MetaClipRegionAction* pAct = (MetaClipRegionAction*) pAction;
1876 if( pAct->IsClipping() )
1877 aClipStack.back() = aMapVDev.LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev.GetMapMode(), GetPrefMapMode() );
1878 else
1879 aClipStack.back() = Rectangle();
1881 break;
1883 case( META_ISECTRECTCLIPREGION_ACTION ):
1885 MetaISectRectClipRegionAction* pAct = (MetaISectRectClipRegionAction*) pAction;
1886 Rectangle aRect( aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ) );
1887 if( aClipStack.back().IsEmpty() )
1888 aClipStack.back() = aRect;
1889 else
1890 aClipStack.back().Intersection( aRect );
1892 break;
1894 case( META_ISECTREGIONCLIPREGION_ACTION ):
1896 MetaISectRegionClipRegionAction* pAct = (MetaISectRegionClipRegionAction*) pAction;
1897 Rectangle aRect( aMapVDev.LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ) );
1898 if( aClipStack.back().IsEmpty() )
1899 aClipStack.back() = aRect;
1900 else
1901 aClipStack.back().Intersection( aRect );
1903 break;
1905 case( META_BMP_ACTION ):
1907 MetaBmpAction* pAct = (MetaBmpAction*) pAction;
1908 Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1909 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1911 break;
1913 case( META_BMPEX_ACTION ):
1915 MetaBmpExAction* pAct = (MetaBmpExAction*) pAction;
1916 Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) );
1917 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1919 break;
1921 case( META_MASK_ACTION ):
1923 MetaMaskAction* pAct = (MetaMaskAction*) pAction;
1924 Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1925 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1927 break;
1929 case( META_MASKSCALE_ACTION ):
1931 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
1932 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1933 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1935 break;
1937 case( META_MASKSCALEPART_ACTION ):
1939 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
1940 Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1941 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1943 break;
1945 case( META_WALLPAPER_ACTION ):
1947 MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction;
1948 Rectangle aRect( pAct->GetRect() );
1949 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1951 break;
1953 case( META_TEXTRECT_ACTION ):
1955 MetaTextRectAction* pAct = (MetaTextRectAction*) pAction;
1956 Rectangle aRect( pAct->GetRect() );
1957 ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
1959 break;
1961 case( META_MOVECLIPREGION_ACTION ):
1963 MetaMoveClipRegionAction* pAct = (MetaMoveClipRegionAction*) pAction;
1964 if( ! aClipStack.back().IsEmpty() )
1966 Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() );
1967 aDelta = aMapVDev.LogicToLogic( aDelta, aMapVDev.GetMapMode(), GetPrefMapMode() );
1968 aClipStack.back().Move( aDelta.Width(), aDelta.Width() );
1971 break;
1973 default:
1975 pAction->Execute( &aMapVDev );
1977 if( nActionType == META_PUSH_ACTION )
1979 MetaPushAction* pAct = (MetaPushAction*) pAction;
1980 aPushFlagStack.push_back( pAct->GetFlags() );
1981 if( (aPushFlagStack.back() & PUSH_CLIPREGION) != 0 )
1983 Rectangle aRect( aClipStack.back() );
1984 aClipStack.push_back( aRect );
1987 else if( nActionType == META_POP_ACTION )
1989 // sanity check
1990 if( ! aPushFlagStack.empty() )
1992 if( (aPushFlagStack.back() & PUSH_CLIPREGION) != 0 )
1994 if( aClipStack.size() > 1 )
1995 aClipStack.pop_back();
1997 aPushFlagStack.pop_back();
2001 break;
2004 return aBound;
2007 // ------------------------------------------------------------------------
2009 Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
2011 return Color( rColor.GetTransparency(),
2012 ( (const ImplColAdjustParam*) pColParam )->pMapR[ rColor.GetRed() ],
2013 ( (const ImplColAdjustParam*) pColParam )->pMapG[ rColor.GetGreen() ],
2014 ( (const ImplColAdjustParam*) pColParam )->pMapB[ rColor.GetBlue() ] );
2018 // ------------------------------------------------------------------------
2020 BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
2022 const ImplBmpAdjustParam* p = (const ImplBmpAdjustParam*) pBmpParam;
2023 BitmapEx aRet( rBmpEx );
2025 aRet.Adjust( p->nLuminancePercent, p->nContrastPercent,
2026 p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent,
2027 p->fGamma, p->bInvert );
2029 return aRet;
2032 // ------------------------------------------------------------------------
2034 Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam )
2036 BYTE cLum = rColor.GetLuminance();
2038 if( MTF_CONVERSION_1BIT_THRESHOLD == ( (const ImplColConvertParam*) pColParam )->eConversion )
2039 cLum = ( cLum < 128 ) ? 0 : 255;
2041 return Color( rColor.GetTransparency(), cLum, cLum, cLum );
2044 // ------------------------------------------------------------------------
2046 BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
2048 BitmapEx aRet( rBmpEx );
2050 aRet.Convert( ( (const ImplBmpConvertParam*) pBmpParam )->eConversion );
2052 return aRet;
2055 // ------------------------------------------------------------------------
2057 Color GDIMetaFile::ImplColMonoFnc( const Color&, const void* pColParam )
2059 return( ( (const ImplColMonoParam*) pColParam )->aColor );
2062 // ------------------------------------------------------------------------
2064 BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
2066 BitmapPalette aPal( 3 );
2068 aPal[ 0 ] = Color( COL_BLACK );
2069 aPal[ 1 ] = Color( COL_WHITE );
2070 aPal[ 2 ] = ( (const ImplBmpMonoParam*) pBmpParam )->aColor;
2072 Bitmap aBmp( rBmpEx.GetSizePixel(), 4, &aPal );
2073 aBmp.Erase( ( (const ImplBmpMonoParam*) pBmpParam )->aColor );
2075 if( rBmpEx.IsAlpha() )
2076 return BitmapEx( aBmp, rBmpEx.GetAlpha() );
2077 else if( rBmpEx.IsTransparent() )
2078 return BitmapEx( aBmp, rBmpEx.GetMask() );
2079 else
2080 return aBmp;
2083 // ------------------------------------------------------------------------
2085 Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam )
2087 const ULONG nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue();
2089 for( ULONG i = 0; i < ( (const ImplColReplaceParam*) pColParam )->nCount; i++ )
2091 if( ( ( (const ImplColReplaceParam*) pColParam )->pMinR[ i ] <= nR ) &&
2092 ( ( (const ImplColReplaceParam*) pColParam )->pMaxR[ i ] >= nR ) &&
2093 ( ( (const ImplColReplaceParam*) pColParam )->pMinG[ i ] <= nG ) &&
2094 ( ( (const ImplColReplaceParam*) pColParam )->pMaxG[ i ] >= nG ) &&
2095 ( ( (const ImplColReplaceParam*) pColParam )->pMinB[ i ] <= nB ) &&
2096 ( ( (const ImplColReplaceParam*) pColParam )->pMaxB[ i ] >= nB ) )
2098 return( ( (const ImplColReplaceParam*) pColParam )->pDstCols[ i ] );
2102 return rColor;
2105 // ------------------------------------------------------------------------
2107 BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
2109 const ImplBmpReplaceParam* p = (const ImplBmpReplaceParam*) pBmpParam;
2110 BitmapEx aRet( rBmpEx );
2112 aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount, p->pTols );
2114 return aRet;
2117 // ------------------------------------------------------------------------
2119 void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam,
2120 BmpExchangeFnc pFncBmp, const void* pBmpParam )
2122 GDIMetaFile aMtf;
2124 aMtf.aPrefSize = aPrefSize;
2125 aMtf.aPrefMapMode = aPrefMapMode;
2127 for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() )
2129 const USHORT nType = pAction->GetType();
2131 switch( nType )
2133 case( META_PIXEL_ACTION ):
2135 MetaPixelAction* pAct = (MetaPixelAction*) pAction;
2136 aMtf.Insert( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND );
2138 break;
2140 case( META_LINECOLOR_ACTION ):
2142 MetaLineColorAction* pAct = (MetaLineColorAction*) pAction;
2144 if( !pAct->IsSetting() )
2145 pAct->Duplicate();
2146 else
2147 pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
2149 aMtf.Insert( pAct, LIST_APPEND );
2151 break;
2153 case( META_FILLCOLOR_ACTION ):
2155 MetaFillColorAction* pAct = (MetaFillColorAction*) pAction;
2157 if( !pAct->IsSetting() )
2158 pAct->Duplicate();
2159 else
2160 pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
2162 aMtf.Insert( pAct, LIST_APPEND );
2164 break;
2166 case( META_TEXTCOLOR_ACTION ):
2168 MetaTextColorAction* pAct = (MetaTextColorAction*) pAction;
2169 aMtf.Insert( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ), LIST_APPEND );
2171 break;
2173 case( META_TEXTFILLCOLOR_ACTION ):
2175 MetaTextFillColorAction* pAct = (MetaTextFillColorAction*) pAction;
2177 if( !pAct->IsSetting() )
2178 pAct->Duplicate();
2179 else
2180 pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
2182 aMtf.Insert( pAct, LIST_APPEND );
2184 break;
2186 case( META_TEXTLINECOLOR_ACTION ):
2188 MetaTextLineColorAction* pAct = (MetaTextLineColorAction*) pAction;
2190 if( !pAct->IsSetting() )
2191 pAct->Duplicate();
2192 else
2193 pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
2195 aMtf.Insert( pAct, LIST_APPEND );
2197 break;
2199 case( META_OVERLINECOLOR_ACTION ):
2201 MetaOverlineColorAction* pAct = (MetaOverlineColorAction*) pAction;
2203 if( !pAct->IsSetting() )
2204 pAct->Duplicate();
2205 else
2206 pAct = new MetaOverlineColorAction( pFncCol( pAct->GetColor(), pColParam ), TRUE );
2208 aMtf.Insert( pAct, LIST_APPEND );
2210 break;
2212 case( META_FONT_ACTION ):
2214 MetaFontAction* pAct = (MetaFontAction*) pAction;
2215 Font aFont( pAct->GetFont() );
2217 aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) );
2218 aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) );
2219 aMtf.Insert( new MetaFontAction( aFont ), LIST_APPEND );
2221 break;
2223 case( META_WALLPAPER_ACTION ):
2225 MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction;
2226 Wallpaper aWall( pAct->GetWallpaper() );
2227 const Rectangle& rRect = pAct->GetRect();
2229 aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) );
2231 if( aWall.IsBitmap() )
2232 aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) );
2234 if( aWall.IsGradient() )
2236 Gradient aGradient( aWall.GetGradient() );
2238 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2239 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2240 aWall.SetGradient( aGradient );
2243 aMtf.Insert( new MetaWallpaperAction( rRect, aWall ), LIST_APPEND );
2245 break;
2247 case( META_BMP_ACTION ):
2248 case( META_BMPEX_ACTION ):
2249 case( META_MASK_ACTION ):
2251 DBG_ERROR( "Don't use bitmap actions of this type in metafiles!" );
2253 break;
2255 case( META_BMPSCALE_ACTION ):
2257 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
2258 aMtf.Insert( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(),
2259 pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ),
2260 LIST_APPEND );
2262 break;
2264 case( META_BMPSCALEPART_ACTION ):
2266 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
2267 aMtf.Insert( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2268 pAct->GetSrcPoint(), pAct->GetSrcSize(),
2269 pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ),
2270 LIST_APPEND );
2272 break;
2274 case( META_BMPEXSCALE_ACTION ):
2276 MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
2277 aMtf.Insert( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(),
2278 pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ),
2279 LIST_APPEND );
2281 break;
2283 case( META_BMPEXSCALEPART_ACTION ):
2285 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
2286 aMtf.Insert( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2287 pAct->GetSrcPoint(), pAct->GetSrcSize(),
2288 pFncBmp( pAct->GetBitmapEx(), pBmpParam ) ),
2289 LIST_APPEND );
2291 break;
2293 case( META_MASKSCALE_ACTION ):
2295 MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction;
2296 aMtf.Insert( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(),
2297 pAct->GetBitmap(),
2298 pFncCol( pAct->GetColor(), pColParam ) ),
2299 LIST_APPEND );
2301 break;
2303 case( META_MASKSCALEPART_ACTION ):
2305 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
2306 aMtf.Insert( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2307 pAct->GetSrcPoint(), pAct->GetSrcSize(),
2308 pAct->GetBitmap(),
2309 pFncCol( pAct->GetColor(), pColParam ) ),
2310 LIST_APPEND );
2312 break;
2314 case( META_GRADIENT_ACTION ):
2316 MetaGradientAction* pAct = (MetaGradientAction*) pAction;
2317 Gradient aGradient( pAct->GetGradient() );
2319 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2320 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2321 aMtf.Insert( new MetaGradientAction( pAct->GetRect(), aGradient ), LIST_APPEND );
2323 break;
2325 case( META_GRADIENTEX_ACTION ):
2327 MetaGradientExAction* pAct = (MetaGradientExAction*) pAction;
2328 Gradient aGradient( pAct->GetGradient() );
2330 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2331 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2332 aMtf.Insert( new MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ), LIST_APPEND );
2334 break;
2336 case( META_HATCH_ACTION ):
2338 MetaHatchAction* pAct = (MetaHatchAction*) pAction;
2339 Hatch aHatch( pAct->GetHatch() );
2341 aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) );
2342 aMtf.Insert( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ), LIST_APPEND );
2344 break;
2346 case( META_FLOATTRANSPARENT_ACTION ):
2348 MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction;
2349 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
2351 aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2352 aMtf.Insert( new MetaFloatTransparentAction( aTransMtf,
2353 pAct->GetPoint(), pAct->GetSize(),
2354 pAct->GetGradient() ),
2355 LIST_APPEND );
2357 break;
2359 case( META_EPS_ACTION ):
2361 MetaEPSAction* pAct = (MetaEPSAction*) pAction;
2362 GDIMetaFile aSubst( pAct->GetSubstitute() );
2364 aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2365 aMtf.Insert( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(),
2366 pAct->GetLink(), aSubst ),
2367 LIST_APPEND );
2369 break;
2371 default:
2373 pAction->Duplicate();
2374 aMtf.Insert( pAction, LIST_APPEND );
2376 break;
2380 *this = aMtf;
2383 // ------------------------------------------------------------------------
2385 void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
2386 short nChannelRPercent, short nChannelGPercent,
2387 short nChannelBPercent, double fGamma, BOOL bInvert )
2389 // nothing to do? => return quickly
2390 if( nLuminancePercent || nContrastPercent ||
2391 nChannelRPercent || nChannelGPercent || nChannelBPercent ||
2392 ( fGamma != 1.0 ) || bInvert )
2394 double fM, fROff, fGOff, fBOff, fOff;
2395 ImplColAdjustParam aColParam;
2396 ImplBmpAdjustParam aBmpParam;
2398 aColParam.pMapR = new BYTE[ 256 ];
2399 aColParam.pMapG = new BYTE[ 256 ];
2400 aColParam.pMapB = new BYTE[ 256 ];
2402 // calculate slope
2403 if( nContrastPercent >= 0 )
2404 fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
2405 else
2406 fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
2408 // total offset = luminance offset + contrast offset
2409 fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
2411 // channel offset = channel offset + total offset
2412 fROff = nChannelRPercent * 2.55 + fOff;
2413 fGOff = nChannelGPercent * 2.55 + fOff;
2414 fBOff = nChannelBPercent * 2.55 + fOff;
2416 // calculate gamma value
2417 fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
2418 const BOOL bGamma = ( fGamma != 1.0 );
2420 // create mapping table
2421 for( long nX = 0L; nX < 256L; nX++ )
2423 aColParam.pMapR[ nX ] = (BYTE) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
2424 aColParam.pMapG[ nX ] = (BYTE) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
2425 aColParam.pMapB[ nX ] = (BYTE) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
2427 if( bGamma )
2429 aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma );
2430 aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma );
2431 aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma );
2434 if( bInvert )
2436 aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ];
2437 aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ];
2438 aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ];
2442 aBmpParam.nLuminancePercent = nLuminancePercent;
2443 aBmpParam.nContrastPercent = nContrastPercent;
2444 aBmpParam.nChannelRPercent = nChannelRPercent;
2445 aBmpParam.nChannelGPercent = nChannelGPercent;
2446 aBmpParam.nChannelBPercent = nChannelBPercent;
2447 aBmpParam.fGamma = fGamma;
2448 aBmpParam.bInvert = bInvert;
2450 // do color adjustment
2451 ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam );
2453 delete[] aColParam.pMapR;
2454 delete[] aColParam.pMapG;
2455 delete[] aColParam.pMapB;
2459 // ------------------------------------------------------------------------
2461 void GDIMetaFile::Convert( MtfConversion eConversion )
2463 // nothing to do? => return quickly
2464 if( eConversion != MTF_CONVERSION_NONE )
2466 ImplColConvertParam aColParam;
2467 ImplBmpConvertParam aBmpParam;
2469 aColParam.eConversion = eConversion;
2470 aBmpParam.eConversion = ( MTF_CONVERSION_1BIT_THRESHOLD == eConversion ) ? BMP_CONVERSION_1BIT_THRESHOLD : BMP_CONVERSION_8BIT_GREYS;
2472 ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam );
2476 // ------------------------------------------------------------------------
2478 void GDIMetaFile::ReplaceColors( const Color& rSearchColor, const Color& rReplaceColor, ULONG nTol )
2480 ReplaceColors( &rSearchColor, &rReplaceColor, 1, &nTol );
2483 // ------------------------------------------------------------------------
2485 void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, ULONG nColorCount, ULONG* pTols )
2487 ImplColReplaceParam aColParam;
2488 ImplBmpReplaceParam aBmpParam;
2490 aColParam.pMinR = new ULONG[ nColorCount ];
2491 aColParam.pMaxR = new ULONG[ nColorCount ];
2492 aColParam.pMinG = new ULONG[ nColorCount ];
2493 aColParam.pMaxG = new ULONG[ nColorCount ];
2494 aColParam.pMinB = new ULONG[ nColorCount ];
2495 aColParam.pMaxB = new ULONG[ nColorCount ];
2497 for( ULONG i = 0; i < nColorCount; i++ )
2499 const long nTol = pTols ? ( pTols[ i ] * 255 ) / 100 : 0;
2500 long nVal;
2502 nVal = pSearchColors[ i ].GetRed();
2503 aColParam.pMinR[ i ] = (ULONG) Max( nVal - nTol, 0L );
2504 aColParam.pMaxR[ i ] = (ULONG) Min( nVal + nTol, 255L );
2506 nVal = pSearchColors[ i ].GetGreen();
2507 aColParam.pMinG[ i ] = (ULONG) Max( nVal - nTol, 0L );
2508 aColParam.pMaxG[ i ] = (ULONG) Min( nVal + nTol, 255L );
2510 nVal = pSearchColors[ i ].GetBlue();
2511 aColParam.pMinB[ i ] = (ULONG) Max( nVal - nTol, 0L );
2512 aColParam.pMaxB[ i ] = (ULONG) Min( nVal + nTol, 255L );
2515 aColParam.pDstCols = pReplaceColors;
2516 aColParam.nCount = nColorCount;
2518 aBmpParam.pSrcCols = pSearchColors;
2519 aBmpParam.pDstCols = pReplaceColors;
2520 aBmpParam.nCount = nColorCount;
2521 aBmpParam.pTols = pTols;
2523 ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam );
2525 delete[] aColParam.pMinR;
2526 delete[] aColParam.pMaxR;
2527 delete[] aColParam.pMinG;
2528 delete[] aColParam.pMaxG;
2529 delete[] aColParam.pMinB;
2530 delete[] aColParam.pMaxB;
2533 // ------------------------------------------------------------------------
2535 GDIMetaFile GDIMetaFile::GetMonochromeMtf( const Color& rColor ) const
2537 GDIMetaFile aRet( *this );
2539 ImplColMonoParam aColParam;
2540 ImplBmpMonoParam aBmpParam;
2542 aColParam.aColor = rColor;
2543 aBmpParam.aColor = rColor;
2545 aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam );
2547 return aRet;
2550 // ------------------------------------------------------------------------
2552 ULONG GDIMetaFile::GetChecksum() const
2554 GDIMetaFile aMtf;
2555 SvMemoryStream aMemStm( 65535, 65535 );
2556 ImplMetaWriteData aWriteData; aWriteData.meActualCharSet = aMemStm.GetStreamCharSet();
2557 SVBT16 aBT16;
2558 SVBT32 aBT32;
2559 ULONG nCrc = 0;
2561 for( ULONG i = 0, nObjCount = GetActionCount(); i < nObjCount; i++ )
2563 MetaAction* pAction = GetAction( i );
2565 switch( pAction->GetType() )
2567 case( META_BMP_ACTION ):
2569 MetaBmpAction* pAct = (MetaBmpAction*) pAction;
2571 ShortToSVBT16( pAct->GetType(), aBT16 );
2572 nCrc = rtl_crc32( nCrc, aBT16, 2 );
2574 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2575 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2577 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2578 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2580 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2581 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2583 break;
2585 case( META_BMPSCALE_ACTION ):
2587 MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
2589 ShortToSVBT16( pAct->GetType(), aBT16 );
2590 nCrc = rtl_crc32( nCrc, aBT16, 2 );
2592 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2593 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2595 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2596 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2598 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2599 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2601 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2602 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2604 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2605 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2607 break;
2609 case( META_BMPSCALEPART_ACTION ):
2611 MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
2613 ShortToSVBT16( pAct->GetType(), aBT16 );
2614 nCrc = rtl_crc32( nCrc, aBT16, 2 );
2616 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2617 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2619 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2620 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2622 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2623 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2625 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2626 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2628 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2629 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2631 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2632 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2634 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2635 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2637 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2638 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2640 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2641 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2643 break;
2645 case( META_BMPEX_ACTION ):
2647 MetaBmpExAction* pAct = (MetaBmpExAction*) pAction;
2649 ShortToSVBT16( pAct->GetType(), aBT16 );
2650 nCrc = rtl_crc32( nCrc, aBT16, 2 );
2652 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
2653 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2655 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2656 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2658 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2659 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2661 break;
2663 case( META_BMPEXSCALE_ACTION ):
2665 MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
2667 ShortToSVBT16( pAct->GetType(), aBT16 );
2668 nCrc = rtl_crc32( nCrc, aBT16, 2 );
2670 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
2671 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2673 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2674 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2676 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2677 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2679 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2680 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2682 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2683 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2685 break;
2687 case( META_BMPEXSCALEPART_ACTION ):
2689 MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
2691 ShortToSVBT16( pAct->GetType(), aBT16 );
2692 nCrc = rtl_crc32( nCrc, aBT16, 2 );
2694 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
2695 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2697 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2698 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2700 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2701 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2703 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2704 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2706 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2707 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2709 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2710 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2712 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2713 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2715 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2716 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2718 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2719 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2721 break;
2723 case( META_MASK_ACTION ):
2725 MetaMaskAction* pAct = (MetaMaskAction*) pAction;
2727 ShortToSVBT16( pAct->GetType(), aBT16 );
2728 nCrc = rtl_crc32( nCrc, aBT16, 2 );
2730 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2731 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2733 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2734 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2736 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2737 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2739 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2740 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2742 break;
2744 case( META_MASKSCALE_ACTION ):
2746 MetaMaskScaleAction* pAct = (MetaMaskScaleAction*) pAction;
2748 ShortToSVBT16( pAct->GetType(), aBT16 );
2749 nCrc = rtl_crc32( nCrc, aBT16, 2 );
2751 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2752 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2754 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2755 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2757 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2758 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2760 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2761 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2763 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2764 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2766 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2767 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2769 break;
2771 case( META_MASKSCALEPART_ACTION ):
2773 MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
2775 ShortToSVBT16( pAct->GetType(), aBT16 );
2776 nCrc = rtl_crc32( nCrc, aBT16, 2 );
2778 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2779 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2781 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2782 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2784 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2785 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2787 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2788 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2790 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2791 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2793 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2794 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2796 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2797 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2799 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2800 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2802 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2803 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2805 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2806 nCrc = rtl_crc32( nCrc, aBT32, 4 );
2808 break;
2810 case META_EPS_ACTION :
2812 MetaEPSAction* pAct = (MetaEPSAction*) pAction;
2813 nCrc = rtl_crc32( nCrc, pAct->GetLink().GetData(), pAct->GetLink().GetDataSize() );
2815 break;
2817 default:
2819 pAction->Write( aMemStm, &aWriteData );
2820 nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() );
2821 aMemStm.Seek( 0 );
2823 break;
2827 return nCrc;
2830 // ------------------------------------------------------------------------
2832 ULONG GDIMetaFile::GetSizeBytes() const
2834 ULONG nSizeBytes = 0;
2836 for( ULONG i = 0, nObjCount = GetActionCount(); i < nObjCount; ++i )
2838 MetaAction* pAction = GetAction( i );
2840 // default action size is set to 32 (=> not the exact value)
2841 nSizeBytes += 32;
2843 // add sizes for large action content
2844 switch( pAction->GetType() )
2846 case( META_BMP_ACTION ): nSizeBytes += ( (MetaBmpAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2847 case( META_BMPSCALE_ACTION ): nSizeBytes += ( (MetaBmpScaleAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2848 case( META_BMPSCALEPART_ACTION ): nSizeBytes += ( (MetaBmpScalePartAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2850 case( META_BMPEX_ACTION ): nSizeBytes += ( (MetaBmpExAction*) pAction )->GetBitmapEx().GetSizeBytes(); break;
2851 case( META_BMPEXSCALE_ACTION ): nSizeBytes += ( (MetaBmpExScaleAction*) pAction )->GetBitmapEx().GetSizeBytes(); break;
2852 case( META_BMPEXSCALEPART_ACTION ): nSizeBytes += ( (MetaBmpExScalePartAction*) pAction )->GetBitmapEx().GetSizeBytes(); break;
2854 case( META_MASK_ACTION ): nSizeBytes += ( (MetaMaskAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2855 case( META_MASKSCALE_ACTION ): nSizeBytes += ( (MetaMaskScaleAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2856 case( META_MASKSCALEPART_ACTION ): nSizeBytes += ( (MetaMaskScalePartAction*) pAction )->GetBitmap().GetSizeBytes(); break;
2858 case( META_POLYLINE_ACTION ): nSizeBytes += ( ( (MetaPolyLineAction*) pAction )->GetPolygon().GetSize() * sizeof( Point ) ); break;
2859 case( META_POLYGON_ACTION ): nSizeBytes += ( ( (MetaPolygonAction*) pAction )->GetPolygon().GetSize() * sizeof( Point ) ); break;
2860 case( META_POLYPOLYGON_ACTION ):
2862 const PolyPolygon& rPolyPoly = ( (MetaPolyPolygonAction*) pAction )->GetPolyPolygon();
2864 for( USHORT n = 0; n < rPolyPoly.Count(); ++n )
2865 nSizeBytes += ( rPolyPoly[ n ].GetSize() * sizeof( Point ) );
2867 break;
2869 case( META_TEXT_ACTION ): nSizeBytes += ( ( (MetaTextAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break;
2870 case( META_STRETCHTEXT_ACTION ): nSizeBytes += ( ( (MetaStretchTextAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break;
2871 case( META_TEXTRECT_ACTION ): nSizeBytes += ( ( (MetaTextRectAction*) pAction )->GetText().Len() * sizeof( sal_Unicode ) ); break;
2872 case( META_TEXTARRAY_ACTION ):
2874 MetaTextArrayAction* pTextArrayAction = (MetaTextArrayAction*) pAction;
2876 nSizeBytes += ( pTextArrayAction->GetText().Len() * sizeof( sal_Unicode ) );
2878 if( pTextArrayAction->GetDXArray() )
2879 nSizeBytes += ( pTextArrayAction->GetLen() << 2 );
2881 break;
2883 default:
2884 break;
2888 return( nSizeBytes );
2891 // ------------------------------------------------------------------------
2893 SvStream& operator>>( SvStream& rIStm, GDIMetaFile& rGDIMetaFile )
2895 if( !rIStm.GetError() )
2897 char aId[ 7 ];
2898 ULONG nStmPos = rIStm.Tell();
2899 USHORT nOldFormat = rIStm.GetNumberFormatInt();
2901 rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
2903 aId[ 0 ] = 0;
2904 aId[ 6 ] = 0;
2905 rIStm.Read( aId, 6 );
2907 if ( !strcmp( aId, "VCLMTF" ) )
2909 // new format
2910 VersionCompat* pCompat;
2911 MetaAction* pAction;
2912 UINT32 nStmCompressMode = 0;
2913 UINT32 nCount = 0;
2915 pCompat = new VersionCompat( rIStm, STREAM_READ );
2917 rIStm >> nStmCompressMode;
2918 rIStm >> rGDIMetaFile.aPrefMapMode;
2919 rIStm >> rGDIMetaFile.aPrefSize;
2920 rIStm >> nCount;
2922 delete pCompat;
2924 ImplMetaReadData aReadData;
2925 aReadData.meActualCharSet = rIStm.GetStreamCharSet();
2927 for( UINT32 nAction = 0UL; ( nAction < nCount ) && !rIStm.IsEof(); nAction++ )
2929 pAction = MetaAction::ReadMetaAction( rIStm, &aReadData );
2931 if( pAction )
2932 rGDIMetaFile.AddAction( pAction );
2935 else
2937 // to avoid possible compiler optimizations => new/delete
2938 rIStm.Seek( nStmPos );
2939 delete( new SVMConverter( rIStm, rGDIMetaFile, CONVERT_FROM_SVM1 ) );
2942 // check for errors
2943 if( rIStm.GetError() )
2945 rGDIMetaFile.Clear();
2946 rIStm.Seek( nStmPos );
2949 rIStm.SetNumberFormatInt( nOldFormat );
2952 return rIStm;
2955 // ------------------------------------------------------------------------
2957 SvStream& operator<<( SvStream& rOStm, const GDIMetaFile& rGDIMetaFile )
2959 if( !rOStm.GetError() )
2961 if( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 )
2962 ((GDIMetaFile&) rGDIMetaFile ).Write( rOStm );
2963 else
2964 delete( new SVMConverter( rOStm, (GDIMetaFile&) rGDIMetaFile, CONVERT_TO_SVM1 ) );
2967 return rOStm;
2970 // ------------------------------------------------------------------------
2972 SvStream& GDIMetaFile::Read( SvStream& rIStm )
2974 Clear();
2975 rIStm >> *this;
2977 return rIStm;
2980 // ------------------------------------------------------------------------
2982 SvStream& GDIMetaFile::Write( SvStream& rOStm )
2984 VersionCompat* pCompat;
2985 const UINT32 nStmCompressMode = rOStm.GetCompressMode();
2986 USHORT nOldFormat = rOStm.GetNumberFormatInt();
2988 rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
2989 rOStm.Write( "VCLMTF", 6 );
2991 pCompat = new VersionCompat( rOStm, STREAM_WRITE, 1 );
2993 rOStm << nStmCompressMode;
2994 rOStm << aPrefMapMode;
2995 rOStm << aPrefSize;
2996 rOStm << (UINT32) GetActionCount();
2998 delete pCompat;
3000 ImplMetaWriteData aWriteData;
3001 aWriteData.meActualCharSet = rOStm.GetStreamCharSet();
3003 MetaAction* pAct = (MetaAction*)First();
3004 while ( pAct )
3006 pAct->Write( rOStm, &aWriteData );
3007 pAct = (MetaAction*)Next();
3010 rOStm.SetNumberFormatInt( nOldFormat );
3012 return rOStm;
3015 // ------------------------------------------------------------------------
3017 BOOL GDIMetaFile::CreateThumbnail( sal_uInt32 nMaximumExtent,
3018 BitmapEx& rBmpEx,
3019 const BitmapEx* pOverlay,
3020 const Rectangle* pOverlayRect ) const
3022 // the implementation is provided by KA
3024 // initialization seems to be complicated but is used to avoid rounding errors
3025 VirtualDevice aVDev;
3026 const Point aNullPt;
3027 const Point aTLPix( aVDev.LogicToPixel( aNullPt, GetPrefMapMode() ) );
3028 const Point aBRPix( aVDev.LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
3029 Size aDrawSize( aVDev.LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
3030 Size aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 );
3031 Point aPosPix;
3033 if ( !rBmpEx.IsEmpty() )
3034 rBmpEx.SetEmpty();
3036 // determine size that has the same aspect ratio as image size and
3037 // fits into the rectangle determined by nMaximumExtent
3038 if ( aSizePix.Width() && aSizePix.Height()
3039 && ( sal::static_int_cast< unsigned long >(aSizePix.Width()) >
3040 nMaximumExtent ||
3041 sal::static_int_cast< unsigned long >(aSizePix.Height()) >
3042 nMaximumExtent ) )
3044 const Size aOldSizePix( aSizePix );
3045 double fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height();
3047 if ( fWH <= 1.0 )
3049 aSizePix.Width() = FRound( nMaximumExtent * fWH );
3050 aSizePix.Height() = nMaximumExtent;
3052 else
3054 aSizePix.Width() = nMaximumExtent;
3055 aSizePix.Height() = FRound( nMaximumExtent / fWH );
3058 aDrawSize.Width() = FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() );
3059 aDrawSize.Height() = FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() );
3062 Size aFullSize;
3063 Point aBackPosPix;
3064 Rectangle aOverlayRect;
3066 // calculate addigtional positions and sizes if an overlay image is used
3067 if ( pOverlay )
3069 aFullSize = Size( nMaximumExtent, nMaximumExtent );
3070 aOverlayRect = Rectangle( aNullPt, aFullSize );
3072 aOverlayRect.Intersection( pOverlayRect ? *pOverlayRect : Rectangle( aNullPt, pOverlay->GetSizePixel() ) );
3074 if ( !aOverlayRect.IsEmpty() )
3075 aBackPosPix = Point( ( nMaximumExtent - aSizePix.Width() ) >> 1, ( nMaximumExtent - aSizePix.Height() ) >> 1 );
3076 else
3077 pOverlay = NULL;
3079 else
3081 aFullSize = aSizePix;
3082 pOverlay = NULL;
3085 // draw image(s) into VDev and get resulting image
3086 if ( aVDev.SetOutputSizePixel( aFullSize ) )
3088 // draw metafile into VDev
3089 const_cast<GDIMetaFile *>(this)->WindStart();
3090 const_cast<GDIMetaFile *>(this)->Play( &aVDev, aBackPosPix, aDrawSize );
3092 // draw overlay if neccessary
3093 if ( pOverlay )
3094 aVDev.DrawBitmapEx( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), *pOverlay );
3096 // get paint bitmap
3097 Bitmap aBmp( aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() ) );
3099 // assure that we have a true color image
3100 if ( aBmp.GetBitCount() != 24 )
3101 aBmp.Convert( BMP_CONVERSION_24BIT );
3103 // create resulting mask bitmap with metafile output set to black
3104 GDIMetaFile aMonchromeMtf( GetMonochromeMtf( COL_BLACK ) );
3105 aVDev.DrawWallpaper( Rectangle( aNullPt, aSizePix ), Wallpaper( Color( COL_WHITE ) ) );
3106 aMonchromeMtf.WindStart();
3107 aMonchromeMtf.Play( &aVDev, aBackPosPix, aDrawSize );
3109 // watch for overlay mask
3110 if ( pOverlay )
3112 Bitmap aOverlayMergeBmp( aVDev.GetBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize() ) );
3114 // create ANDed resulting mask at overlay area
3115 if ( pOverlay->IsTransparent() )
3116 aVDev.DrawBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), pOverlay->GetMask() );
3117 else
3119 aVDev.SetLineColor( COL_BLACK );
3120 aVDev.SetFillColor( COL_BLACK );
3121 aVDev.DrawRect( aOverlayRect);
3124 aOverlayMergeBmp.CombineSimple( aVDev.GetBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize() ), BMP_COMBINE_AND );
3125 aVDev.DrawBitmap( aOverlayRect.TopLeft(), aOverlayRect.GetSize(), aOverlayMergeBmp );
3128 rBmpEx = BitmapEx( aBmp, aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() ) );
3131 return !rBmpEx.IsEmpty();
3134 void GDIMetaFile::UseCanvas( BOOL _bUseCanvas )
3136 bUseCanvas = _bUseCanvas;
3139 // ------------------------------------------------------------------------
3141 MetaCommentAction* makePluggableRendererAction( const rtl::OUString& rRendererServiceName,
3142 const rtl::OUString& rGraphicServiceName,
3143 const void* _pData,
3144 sal_uInt32 nDataSize )
3146 const BYTE* pData=(BYTE*)_pData;
3148 // data gets copied twice, unfortunately
3149 rtl::OString aRendererServiceName(
3150 rRendererServiceName.getStr(),
3151 rRendererServiceName.getLength(),
3152 RTL_TEXTENCODING_ASCII_US);
3153 rtl::OString aGraphicServiceName(
3154 rGraphicServiceName.getStr(),
3155 rGraphicServiceName.getLength(),
3156 RTL_TEXTENCODING_ASCII_US);
3158 std::vector<sal_uInt8> aMem(
3159 aRendererServiceName.getLength()+
3160 aGraphicServiceName.getLength()+2+nDataSize);
3161 sal_uInt8* pMem=&aMem[0];
3163 std::copy(aRendererServiceName.getStr(),
3164 aRendererServiceName.getStr()+aRendererServiceName.getLength()+1,
3165 pMem);
3166 pMem+=aRendererServiceName.getLength()+1;
3167 std::copy(aGraphicServiceName.getStr(),
3168 aGraphicServiceName.getStr()+aGraphicServiceName.getLength()+1,
3169 pMem);
3170 pMem+=aGraphicServiceName.getLength()+1;
3172 std::copy(pData,pData+nDataSize,
3173 pMem);
3175 return new MetaCommentAction(
3176 "DELEGATE_PLUGGABLE_RENDERER",
3178 &aMem[0],
3179 aMem.size());