LCOV - code coverage report
Current view: top level - vcl/source/gdi - gdimtf.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 569 1477 38.5 %
Date: 2015-06-13 12:38:46 Functions: 40 65 61.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <rtl/crc.h>
      21             : #include <tools/stream.hxx>
      22             : #include <tools/vcompat.hxx>
      23             : #include <tools/fract.hxx>
      24             : #include <vcl/metaact.hxx>
      25             : #include <vcl/salbtype.hxx>
      26             : #include <vcl/outdev.hxx>
      27             : #include <vcl/window.hxx>
      28             : #include <vcl/virdev.hxx>
      29             : #include <vcl/svapp.hxx>
      30             : #include <vcl/gdimtf.hxx>
      31             : #include <vcl/graphictools.hxx>
      32             : #include <basegfx/polygon/b2dpolygon.hxx>
      33             : #include <vcl/canvastools.hxx>
      34             : 
      35             : #include <cvtsvm.hxx>
      36             : #include <salbmp.hxx>
      37             : #include <salinst.hxx>
      38             : #include <svdata.hxx>
      39             : 
      40             : #include <com/sun/star/beans/XFastPropertySet.hpp>
      41             : #include <com/sun/star/rendering/MtfRenderer.hpp>
      42             : #include <com/sun/star/rendering/XBitmapCanvas.hpp>
      43             : #include <com/sun/star/rendering/XCanvas.hpp>
      44             : #include <comphelper/processfactory.hxx>
      45             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      46             : #include <com/sun/star/lang/XInitialization.hpp>
      47             : #include <com/sun/star/awt/XGraphics.hpp>
      48             : #include <com/sun/star/graphic/XGraphic.hpp>
      49             : #include <com/sun/star/graphic/XGraphicRenderer.hpp>
      50             : 
      51             : using namespace com::sun::star;
      52             : 
      53             : #define GAMMA( _def_cVal, _def_InvGamma )   ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
      54             : 
      55             : struct ImplColAdjustParam
      56             : {
      57             :     sal_uInt8*  pMapR;
      58             :     sal_uInt8*  pMapG;
      59             :     sal_uInt8*  pMapB;
      60             : };
      61             : 
      62             : struct ImplBmpAdjustParam
      63             : {
      64             :     short   nLuminancePercent;
      65             :     short   nContrastPercent;
      66             :     short   nChannelRPercent;
      67             :     short   nChannelGPercent;
      68             :     short   nChannelBPercent;
      69             :     double  fGamma;
      70             :     bool    bInvert;
      71             : };
      72             : 
      73             : struct ImplColConvertParam
      74             : {
      75             :     MtfConversion   eConversion;
      76             : };
      77             : 
      78             : struct ImplBmpConvertParam
      79             : {
      80             :     BmpConversion   eConversion;
      81             : };
      82             : 
      83          41 : struct ImplColMonoParam
      84             : {
      85             :     Color aColor;
      86             : };
      87             : 
      88          41 : struct ImplBmpMonoParam
      89             : {
      90             :     Color aColor;
      91             : };
      92             : 
      93             : struct ImplColReplaceParam
      94             : {
      95             :     sal_uLong*          pMinR;
      96             :     sal_uLong*          pMaxR;
      97             :     sal_uLong*          pMinG;
      98             :     sal_uLong*          pMaxG;
      99             :     sal_uLong*          pMinB;
     100             :     sal_uLong*          pMaxB;
     101             :     const Color*    pDstCols;
     102             :     sal_uLong           nCount;
     103             : };
     104             : 
     105             : struct ImplBmpReplaceParam
     106             : {
     107             :     const Color*    pSrcCols;
     108             :     const Color*    pDstCols;
     109             :     sal_uLong           nCount;
     110             :     const sal_uLong*    pTols;
     111             : };
     112             : 
     113      346240 : GDIMetaFile::GDIMetaFile() :
     114             :     nCurrentActionElement( 0 ),
     115             :     aPrefSize   ( 1, 1 ),
     116             :     pPrev       ( NULL ),
     117             :     pNext       ( NULL ),
     118             :     pOutDev     ( NULL ),
     119             :     bPause      ( false ),
     120             :     bRecord     ( false ),
     121      346240 :     bUseCanvas  ( false )
     122             : {
     123      346240 : }
     124             : 
     125       21589 : GDIMetaFile::GDIMetaFile( const GDIMetaFile& rMtf ) :
     126             :     nCurrentActionElement( rMtf.nCurrentActionElement ),
     127             :     aPrefMapMode    ( rMtf.aPrefMapMode ),
     128             :     aPrefSize       ( rMtf.aPrefSize ),
     129             :     aHookHdlLink    ( rMtf.aHookHdlLink ),
     130             :     pPrev           ( rMtf.pPrev ),
     131             :     pNext           ( rMtf.pNext ),
     132             :     pOutDev         ( NULL ),
     133             :     bPause          ( false ),
     134             :     bRecord         ( false ),
     135       21589 :     bUseCanvas      ( rMtf.bUseCanvas )
     136             : {
     137             :     // Increment RefCount of MetaActions
     138      620420 :     for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
     139             :     {
     140      598831 :         rMtf.GetAction( i )->Duplicate();
     141      598831 :         aList.push_back( rMtf.GetAction( i ) );
     142             :     }
     143             : 
     144       21589 :     if( rMtf.bRecord )
     145             :     {
     146           0 :         Record( rMtf.pOutDev );
     147             : 
     148           0 :         if ( rMtf.bPause )
     149           0 :             Pause( true );
     150             :     }
     151       21589 : }
     152             : 
     153      740664 : GDIMetaFile::~GDIMetaFile()
     154             : {
     155      367653 :     Clear();
     156      373011 : }
     157             : 
     158       39121 : size_t GDIMetaFile::GetActionSize() const
     159             : {
     160       39121 :     return aList.size();
     161             : }
     162             : 
     163     2119477 : MetaAction* GDIMetaFile::GetAction( size_t nAction ) const
     164             : {
     165     2119477 :     return (nAction < aList.size()) ? aList[ nAction ] : NULL;
     166             : }
     167             : 
     168        5622 : MetaAction* GDIMetaFile::FirstAction()
     169             : {
     170        5622 :     nCurrentActionElement = 0;
     171        5622 :     return aList.empty() ? NULL : aList[ 0 ];
     172             : }
     173             : 
     174      820447 : MetaAction* GDIMetaFile::NextAction()
     175             : {
     176      820447 :     return ( nCurrentActionElement + 1 < aList.size() ) ? aList[ ++nCurrentActionElement ] : NULL;
     177             : }
     178             : 
     179           0 : MetaAction* GDIMetaFile::ReplaceAction( MetaAction* pAction, size_t nAction )
     180             : {
     181           0 :     if ( nAction >= aList.size() )
     182             :     {
     183             :         // this method takes ownership of pAction and is
     184             :         // therefore responsible for deleting it
     185           0 :         pAction->Delete();
     186           0 :         return NULL;
     187             :     }
     188             :     //fdo#39995 This does't increment the incoming action ref-count nor does it
     189             :     //decrement the outgoing action ref-count
     190           0 :     std::swap(pAction, aList[nAction]);
     191           0 :     return pAction;
     192             : }
     193             : 
     194        5211 : GDIMetaFile& GDIMetaFile::operator=( const GDIMetaFile& rMtf )
     195             : {
     196        5211 :     if( this != &rMtf )
     197             :     {
     198        5211 :         Clear();
     199             : 
     200             :         // Increment RefCount of MetaActions
     201      333410 :         for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
     202             :         {
     203      328199 :             rMtf.GetAction( i )->Duplicate();
     204      328199 :             aList.push_back( rMtf.GetAction( i ) );
     205             :         }
     206             : 
     207        5211 :         aPrefMapMode = rMtf.aPrefMapMode;
     208        5211 :         aPrefSize = rMtf.aPrefSize;
     209        5211 :         aHookHdlLink = rMtf.aHookHdlLink;
     210        5211 :         pPrev = rMtf.pPrev;
     211        5211 :         pNext = rMtf.pNext;
     212        5211 :         pOutDev = NULL;
     213        5211 :         bPause = false;
     214        5211 :         bRecord = false;
     215        5211 :         bUseCanvas = rMtf.bUseCanvas;
     216             : 
     217        5211 :         if( rMtf.bRecord )
     218             :         {
     219           0 :             Record( rMtf.pOutDev );
     220             : 
     221           0 :             if( rMtf.bPause )
     222           0 :                 Pause( true );
     223             :         }
     224             :     }
     225             : 
     226        5211 :     return *this;
     227             : }
     228             : 
     229         112 : bool GDIMetaFile::operator==( const GDIMetaFile& rMtf ) const
     230             : {
     231         112 :     const size_t    nObjCount = aList.size();
     232         112 :     bool        bRet = false;
     233             : 
     234         112 :     if( this == &rMtf )
     235           0 :         bRet = true;
     236         336 :     else if( rMtf.GetActionSize()  == nObjCount &&
     237         224 :              rMtf.GetPrefSize()    == aPrefSize &&
     238         112 :              rMtf.GetPrefMapMode() == aPrefMapMode )
     239             :     {
     240         112 :         bRet = true;
     241             : 
     242        6717 :         for( size_t n = 0; n < nObjCount; n++ )
     243             :         {
     244        6605 :             if( aList[ n ] != rMtf.GetAction( n ) )
     245             :             {
     246           0 :                 bRet = false;
     247           0 :                 break;
     248             :             }
     249             :         }
     250             :     }
     251             : 
     252         112 :     return bRet;
     253             : }
     254             : 
     255      725403 : void GDIMetaFile::Clear()
     256             : {
     257      725403 :     if( bRecord )
     258           0 :         Stop();
     259             : 
     260     2780966 :     for( size_t i = 0, n = aList.size(); i < n; ++i )
     261     2055563 :         aList[ i ]->Delete();
     262      725403 :     aList.clear();
     263      725403 : }
     264             : 
     265       20844 : void GDIMetaFile::Linker( OutputDevice* pOut, bool bLink )
     266             : {
     267       20844 :     if( bLink )
     268             :     {
     269       10422 :         pNext = NULL;
     270       10422 :         pPrev = pOut->GetConnectMetaFile();
     271       10422 :         pOut->SetConnectMetaFile( this );
     272             : 
     273       10422 :         if( pPrev )
     274           0 :             pPrev->pNext = this;
     275             :     }
     276             :     else
     277             :     {
     278       10422 :         if( pNext )
     279             :         {
     280           0 :             pNext->pPrev = pPrev;
     281             : 
     282           0 :             if( pPrev )
     283           0 :                 pPrev->pNext = pNext;
     284             :         }
     285             :         else
     286             :         {
     287       10422 :             if( pPrev )
     288           0 :                 pPrev->pNext = NULL;
     289             : 
     290       10422 :             pOut->SetConnectMetaFile( pPrev );
     291             :         }
     292             : 
     293       10422 :         pPrev = NULL;
     294       10422 :         pNext = NULL;
     295             :     }
     296       20844 : }
     297             : 
     298      442049 : long GDIMetaFile::Hook()
     299             : {
     300      442049 :     return aHookHdlLink.Call( this );
     301             : }
     302             : 
     303       10422 : void GDIMetaFile::Record( OutputDevice* pOut )
     304             : {
     305       10422 :     if( bRecord )
     306           0 :         Stop();
     307             : 
     308       10422 :     nCurrentActionElement = aList.empty() ? 0 : (aList.size() - 1);
     309       10422 :     pOutDev = pOut;
     310       10422 :     bRecord = true;
     311       10422 :     Linker( pOut, true );
     312       10422 : }
     313             : 
     314           8 : void GDIMetaFile::Play( GDIMetaFile& rMtf, size_t nPos )
     315             : {
     316           8 :     if ( !bRecord && !rMtf.bRecord )
     317             :     {
     318           8 :         MetaAction* pAction = GetCurAction();
     319           8 :         const size_t nObjCount = aList.size();
     320             : 
     321           8 :         rMtf.UseCanvas( rMtf.GetUseCanvas() || bUseCanvas );
     322             : 
     323           8 :         if( nPos > nObjCount )
     324           8 :             nPos = nObjCount;
     325             : 
     326         199 :         for( size_t nCurPos = nCurrentActionElement; nCurPos < nPos; nCurPos++ )
     327             :         {
     328         191 :             if( !Hook() && pAction )
     329             :             {
     330         191 :                 pAction->Duplicate();
     331         191 :                 rMtf.AddAction( pAction );
     332             :             }
     333             : 
     334         191 :             pAction = NextAction();
     335             :         }
     336             :     }
     337           8 : }
     338             : 
     339       13021 : void GDIMetaFile::Play( OutputDevice* pOut, size_t nPos )
     340             : {
     341       13021 :     if( !bRecord )
     342             :     {
     343       13021 :         MetaAction* pAction = GetCurAction();
     344       13021 :         const size_t nObjCount = aList.size();
     345       13021 :         size_t  nSyncCount = ( pOut->GetOutDevType() == OUTDEV_WINDOW ) ? 0x000000ff : 0xffffffff;
     346             : 
     347       13021 :         if( nPos > nObjCount )
     348       13021 :             nPos = nObjCount;
     349             : 
     350             :         // #i23407# Set backwards-compatible text language and layout mode
     351             :         // This is necessary, since old metafiles don't even know of these
     352             :         // recent add-ons. Newer metafiles must of course explicitly set
     353             :         // those states.
     354       13021 :         pOut->Push( PushFlags::TEXTLAYOUTMODE|PushFlags::TEXTLANGUAGE );
     355       13021 :         pOut->SetLayoutMode( TEXT_LAYOUT_DEFAULT );
     356       13021 :         pOut->SetDigitLanguage( 0 );
     357             : 
     358             :         OSL_TRACE("GDIMetaFile::Play on device of size: %ld x %ld", pOut->GetOutputSizePixel().Width(), pOut->GetOutputSizePixel().Height());
     359             : 
     360       13021 :         if( !ImplPlayWithRenderer( pOut, Point(0,0), pOut->GetOutputSize() ) ) {
     361       13021 :             size_t  i  = 0;
     362      454879 :             for( size_t nCurPos = nCurrentActionElement; nCurPos < nPos; nCurPos++ )
     363             :             {
     364      441858 :                 if( !Hook() && pAction )
     365             :                 {
     366      444340 :                     if( pAction->GetType() == MetaActionType::COMMENT &&
     367        2482 :                         static_cast<MetaCommentAction*>(pAction)->GetComment() == "DELEGATE_PLUGGABLE_RENDERER" )
     368             :                     {
     369           0 :                         ImplDelegate2PluggableRenderer(static_cast<MetaCommentAction*>(pAction), pOut);
     370             :                     }
     371             :                     else
     372             :                     {
     373      441858 :                         pAction->Execute( pOut );
     374             :                     }
     375             : 
     376             :                     // flush output from time to time
     377      441858 :                     if( i++ > nSyncCount )
     378             :                     {
     379           0 :                         static_cast<vcl::Window*>( pOut )->Flush();
     380           0 :                         i = 0;
     381             :                     }
     382             :                 }
     383             : 
     384      441858 :                 pAction = NextAction();
     385             :             }
     386             :         }
     387       13021 :         pOut->Pop();
     388             :     }
     389       13021 : }
     390             : 
     391       13261 : bool GDIMetaFile::ImplPlayWithRenderer( OutputDevice* pOut, const Point& rPos, Size rLogicDestSize )
     392             : {
     393       13261 :     if (!bUseCanvas)
     394       13175 :         return false;
     395             : 
     396          86 :     Size rDestSize( pOut->LogicToPixel( rLogicDestSize ) );
     397             : 
     398          86 :     const vcl::Window* win = dynamic_cast <vcl::Window*> ( pOut );
     399             : 
     400          86 :     if (!win)
     401          86 :         win = Application::GetActiveTopWindow();
     402          86 :     if (!win)
     403          82 :         win = Application::GetFirstTopLevelWindow();
     404             : 
     405          86 :     if (!win)
     406           0 :         return false;
     407             : 
     408             :     try
     409             :     {
     410          86 :         uno::Reference<rendering::XCanvas> xCanvas = win->GetCanvas ();
     411             : 
     412          86 :         if (!xCanvas.is())
     413          84 :             return false;
     414             : 
     415           2 :         Size aSize (rDestSize.Width () + 1, rDestSize.Height () + 1);
     416           2 :         uno::Reference<rendering::XBitmap> xBitmap = xCanvas->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize));
     417           2 :         if( xBitmap.is () )
     418             :         {
     419           2 :             uno::Reference< rendering::XBitmapCanvas > xBitmapCanvas( xBitmap, uno::UNO_QUERY );
     420           2 :             if( xBitmapCanvas.is() )
     421             :             {
     422           2 :                 uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
     423           2 :                 uno::Reference< rendering::XMtfRenderer > xMtfRenderer = rendering::MtfRenderer::createWithBitmapCanvas( xContext, xBitmapCanvas );
     424             : 
     425           2 :                 xBitmapCanvas->clear();
     426           2 :                 uno::Reference< beans::XFastPropertySet > xMtfFastPropertySet( xMtfRenderer, uno::UNO_QUERY );
     427           2 :                 if( xMtfFastPropertySet.is() )
     428             :                     // set this metafile to the renderer to
     429             :                     // speedup things (instead of copying data to
     430             :                     // sequence of bytes passed to renderer)
     431           2 :                     xMtfFastPropertySet->setFastPropertyValue( 0, uno::Any( reinterpret_cast<sal_Int64>( this ) ) );
     432             : 
     433           2 :                 xMtfRenderer->draw( rDestSize.Width(), rDestSize.Height() );
     434             : 
     435           2 :                 BitmapEx aBitmapEx;
     436           2 :                 if( aBitmapEx.Create( xBitmapCanvas, aSize ) )
     437             :                 {
     438           2 :                     if ( pOut->GetMapMode() == MAP_PIXEL )
     439           0 :                         pOut->DrawBitmapEx( rPos, aBitmapEx );
     440             :                     else
     441           2 :                         pOut->DrawBitmapEx( rPos, rLogicDestSize, aBitmapEx );
     442           2 :                     return true;
     443           0 :                 }
     444           0 :             }
     445           0 :         }
     446             :     }
     447           0 :     catch (const uno::RuntimeException& )
     448             :     {
     449           0 :         throw; // runtime errors are fatal
     450             :     }
     451           0 :     catch (const uno::Exception& e)
     452             :     {
     453             :         // ignore errors, no way of reporting them here
     454             :         SAL_WARN("vcl",
     455             :             "GDIMetaFile::ImplPlayWithRenderer: exception: " << e.Message);
     456             :     }
     457             : 
     458           0 :     return false;
     459             : }
     460             : 
     461           0 : void GDIMetaFile::ImplDelegate2PluggableRenderer( const MetaCommentAction* pAct, OutputDevice* pOut )
     462             : {
     463             :     OSL_ASSERT( pAct->GetComment() == "DELEGATE_PLUGGABLE_RENDERER" );
     464             : 
     465             :     // read payload - string of service name, followed by raw render input
     466           0 :     const sal_uInt8* pData = pAct->GetData();
     467           0 :     const sal_uInt8* const pEndData = pData + pAct->GetDataSize();
     468           0 :     if( !pData )
     469           0 :         return;
     470             : 
     471           0 :     OUStringBuffer aBuffer;
     472           0 :     while( pData<pEndData && *pData )
     473           0 :         aBuffer.append(static_cast<sal_Unicode>(*pData++));
     474           0 :     const OUString aRendererServiceName=aBuffer.makeStringAndClear();
     475           0 :     ++pData;
     476             : 
     477           0 :     while( pData<pEndData && *pData )
     478           0 :         aBuffer.append(static_cast<sal_Unicode>(*pData++));
     479           0 :     const OUString aGraphicServiceName=aBuffer.makeStringAndClear();
     480           0 :     ++pData;
     481             : 
     482           0 :     uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
     483           0 :     if( pData<pEndData )
     484             :     {
     485             :         try
     486             :         {
     487             :             // instantiate render service
     488           0 :             uno::Sequence<uno::Any> aRendererArgs(1);
     489           0 :             aRendererArgs[0] = makeAny(uno::Reference<awt::XGraphics>(pOut->CreateUnoGraphics()));
     490             :             uno::Reference<graphic::XGraphicRenderer> xRenderer(
     491           0 :                 xFactory->createInstanceWithArguments(
     492             :                     aRendererServiceName,
     493           0 :                     aRendererArgs),
     494           0 :                 uno::UNO_QUERY );
     495             : 
     496             :             // instantiate graphic service
     497             :             uno::Reference<graphic::XGraphic> xGraphic(
     498           0 :                 xFactory->createInstance(
     499           0 :                     aGraphicServiceName),
     500           0 :                 uno::UNO_QUERY );
     501             : 
     502             :             uno::Reference<lang::XInitialization> xInit(
     503           0 :                 xGraphic, uno::UNO_QUERY);
     504             : 
     505           0 :             if(xGraphic.is() && xRenderer.is() && xInit.is())
     506             :             {
     507             :                 // delay intialization of XGraphic, to only expose
     508             :                 // XGraphic-generating services to arbitrary binary data
     509             :                 uno::Sequence< sal_Int8 > aSeq(
     510           0 :                     reinterpret_cast<sal_Int8 const *>(pData), pEndData-pData );
     511           0 :                 uno::Sequence<uno::Any> aGraphicsArgs(1);
     512           0 :                 aGraphicsArgs[0] = makeAny(aSeq);
     513           0 :                 xInit->initialize(aGraphicsArgs);
     514             : 
     515           0 :                 xRenderer->render(xGraphic);
     516           0 :             }
     517             :         }
     518           0 :         catch (const uno::RuntimeException&)
     519             :         {
     520             :             // runtime errors are fatal
     521           0 :             throw;
     522             :         }
     523           0 :         catch (const uno::Exception& e)
     524             :         {
     525             :             // ignore errors, no way of reporting them here
     526             :             SAL_WARN("vcl", "GDIMetaFile::ImplDelegate2PluggableRenderer:"
     527             :                     " exception: " << e.Message);
     528             :         }
     529           0 :     }
     530             : }
     531             : 
     532         280 : void GDIMetaFile::Play( OutputDevice* pOut, const Point& rPos,
     533             :                         const Size& rSize, size_t nPos )
     534             : {
     535         280 :     vcl::Region  aDrawClipRegion;
     536         558 :     MapMode aDrawMap( GetPrefMapMode() );
     537         280 :     Size    aDestSize( pOut->LogicToPixel( rSize ) );
     538             : 
     539         280 :     if( aDestSize.Width() && aDestSize.Height() )
     540             :     {
     541         240 :         GDIMetaFile*    pMtf = pOut->GetConnectMetaFile();
     542             : 
     543         240 :         if( ImplPlayWithRenderer( pOut, rPos, rSize ) )
     544         282 :             return;
     545             : 
     546         238 :         Size aTmpPrefSize( pOut->LogicToPixel( GetPrefSize(), aDrawMap ) );
     547             : 
     548         238 :         if( !aTmpPrefSize.Width() )
     549           0 :             aTmpPrefSize.Width() = aDestSize.Width();
     550             : 
     551         238 :         if( !aTmpPrefSize.Height() )
     552           0 :             aTmpPrefSize.Height() = aDestSize.Height();
     553             : 
     554         238 :         Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() );
     555         476 :         Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() );
     556             : 
     557         238 :         aScaleX *= aDrawMap.GetScaleX(); aDrawMap.SetScaleX( aScaleX );
     558         238 :         aScaleY *= aDrawMap.GetScaleY(); aDrawMap.SetScaleY( aScaleY );
     559             : 
     560             :         // #i47260# Convert logical output position to offset within
     561             :         // the metafile's mapmode. Therefore, disable pixel offset on
     562             :         // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
     563             :         // different mapmode (the one currently set on pOut, that is)
     564             :         // - thus, aDrawMap's origin would generally be wrong. And
     565             :         // even _if_ aDrawMap is similar to pOutDev's current mapmode,
     566             :         // it's _still_ undesirable to have pixel offset unequal zero,
     567             :         // because one would still get round-off errors (the
     568             :         // round-trip error for LogicToPixel( PixelToLogic() ) was the
     569             :         // reason for having pixel offset in the first place).
     570         238 :         const Size& rOldOffset( pOut->GetPixelOffset() );
     571         238 :         const Size  aEmptySize;
     572         238 :         pOut->SetPixelOffset( aEmptySize );
     573         238 :         aDrawMap.SetOrigin( pOut->PixelToLogic( pOut->LogicToPixel( rPos ), aDrawMap ) );
     574         238 :         pOut->SetPixelOffset( rOldOffset );
     575             : 
     576         238 :         pOut->Push();
     577             : 
     578         238 :         if ( pMtf && pMtf->IsRecord() && ( pOut->GetOutDevType() != OUTDEV_PRINTER ) )
     579          48 :             pOut->SetRelativeMapMode( aDrawMap );
     580             :         else
     581         190 :             pOut->SetMapMode( aDrawMap );
     582             : 
     583             :         // #i23407# Set backwards-compatible text language and layout mode
     584             :         // This is necessary, since old metafiles don't even know of these
     585             :         // recent add-ons. Newer metafiles must of course explicitly set
     586             :         // those states.
     587         238 :         pOut->SetLayoutMode( TEXT_LAYOUT_DEFAULT );
     588         238 :         pOut->SetDigitLanguage( 0 );
     589             : 
     590         238 :         Play( pOut, nPos );
     591             : 
     592         476 :         pOut->Pop();
     593         278 :     }
     594             : }
     595             : 
     596           0 : void GDIMetaFile::Pause( bool _bPause )
     597             : {
     598           0 :     if( bRecord )
     599             :     {
     600           0 :         if( _bPause )
     601             :         {
     602           0 :             if( !bPause )
     603           0 :                 Linker( pOutDev, false );
     604             :         }
     605             :         else
     606             :         {
     607           0 :             if( bPause )
     608           0 :                 Linker( pOutDev, true );
     609             :         }
     610             : 
     611           0 :         bPause = _bPause;
     612             :     }
     613           0 : }
     614             : 
     615       10426 : void GDIMetaFile::Stop()
     616             : {
     617       10426 :     if( bRecord )
     618             :     {
     619       10422 :         bRecord = false;
     620             : 
     621       10422 :         if( !bPause )
     622       10422 :             Linker( pOutDev, false );
     623             :         else
     624           0 :             bPause = false;
     625             :     }
     626       10426 : }
     627             : 
     628       13555 : void GDIMetaFile::WindStart()
     629             : {
     630       13555 :     if( !bRecord )
     631       13555 :         nCurrentActionElement = 0;
     632       13555 : }
     633             : 
     634           0 : void GDIMetaFile::WindPrev()
     635             : {
     636           0 :     if( !bRecord )
     637           0 :         if ( nCurrentActionElement > 0 )
     638           0 :             --nCurrentActionElement;
     639           0 : }
     640             : 
     641     1128445 : void GDIMetaFile::AddAction( MetaAction* pAction )
     642             : {
     643     1128445 :     aList.push_back( pAction );
     644             : 
     645     1128445 :     if( pPrev )
     646             :     {
     647           0 :         pAction->Duplicate();
     648           0 :         pPrev->AddAction( pAction );
     649             :     }
     650     1128445 : }
     651             : 
     652           0 : void GDIMetaFile::AddAction( MetaAction* pAction, size_t nPos )
     653             : {
     654           0 :     if ( nPos < aList.size() )
     655             :     {
     656           0 :         ::std::vector< MetaAction* >::iterator it = aList.begin();
     657           0 :         ::std::advance( it, nPos );
     658           0 :         aList.insert( it, pAction );
     659             :     }
     660             :     else
     661             :     {
     662           0 :         aList.push_back( pAction );
     663             :     }
     664             : 
     665           0 :     if( pPrev )
     666             :     {
     667           0 :         pAction->Duplicate();
     668           0 :         pPrev->AddAction( pAction, nPos );
     669             :     }
     670           0 : }
     671             : 
     672          88 : void GDIMetaFile::push_back( MetaAction* pAction )
     673             : {
     674          88 :     aList.push_back( pAction );
     675          88 : }
     676             : 
     677           0 : void GDIMetaFile::RemoveAction( size_t nPos )
     678             : {
     679           0 :     if ( nPos < aList.size() )
     680             :     {
     681           0 :         ::std::vector< MetaAction* >::iterator it = aList.begin();
     682           0 :         ::std::advance( it, nPos );
     683           0 :         (*it)->Delete();
     684           0 :         aList.erase( it );
     685             : 
     686             :     }
     687             : 
     688           0 :     if( pPrev )
     689           0 :         pPrev->RemoveAction( nPos );
     690           0 : }
     691             : 
     692           0 : bool GDIMetaFile::Mirror( BmpMirrorFlags nMirrorFlags )
     693             : {
     694           0 :     const Size  aOldPrefSize( GetPrefSize() );
     695             :     long        nMoveX, nMoveY;
     696             :     double      fScaleX, fScaleY;
     697             :     bool        bRet;
     698             : 
     699           0 :     if( nMirrorFlags & BmpMirrorFlags::Horizontal )
     700           0 :         nMoveX = SAL_ABS( aOldPrefSize.Width() ) - 1, fScaleX = -1.0;
     701             :     else
     702           0 :         nMoveX = 0, fScaleX = 1.0;
     703             : 
     704           0 :     if( nMirrorFlags & BmpMirrorFlags::Vertical )
     705           0 :         nMoveY = SAL_ABS( aOldPrefSize.Height() ) - 1, fScaleY = -1.0;
     706             :     else
     707           0 :         nMoveY = 0, fScaleY = 1.0;
     708             : 
     709           0 :     if( ( fScaleX != 1.0 ) || ( fScaleY != 1.0 ) )
     710             :     {
     711           0 :         Scale( fScaleX, fScaleY );
     712           0 :         Move( nMoveX, nMoveY );
     713           0 :         SetPrefSize( aOldPrefSize );
     714           0 :         bRet = true;
     715             :     }
     716             :     else
     717           0 :         bRet = false;
     718             : 
     719           0 :     return bRet;
     720             : }
     721             : 
     722         265 : void GDIMetaFile::Move( long nX, long nY )
     723             : {
     724         265 :     const Size      aBaseOffset( nX, nY );
     725         265 :     Size            aOffset( aBaseOffset );
     726         265 :     ScopedVclPtrInstance< VirtualDevice > aMapVDev;
     727             : 
     728         265 :     aMapVDev->EnableOutput( false );
     729         265 :     aMapVDev->SetMapMode( GetPrefMapMode() );
     730             : 
     731       17439 :     for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
     732             :     {
     733       17174 :         const MetaActionType nType = pAct->GetType();
     734             :         MetaAction* pModAct;
     735             : 
     736       17174 :         if( pAct->GetRefCount() > 1 )
     737             :         {
     738         283 :             aList[ nCurrentActionElement ] = pModAct = pAct->Clone();
     739         283 :             pAct->Delete();
     740             :         }
     741             :         else
     742       16891 :             pModAct = pAct;
     743             : 
     744       17174 :         if( ( MetaActionType::MAPMODE == nType ) ||
     745       16833 :             ( MetaActionType::PUSH == nType ) ||
     746             :             ( MetaActionType::POP == nType ) )
     747             :         {
     748         642 :             pModAct->Execute( aMapVDev.get() );
     749         642 :             aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
     750             :         }
     751             : 
     752       17174 :         pModAct->Move( aOffset.Width(), aOffset.Height() );
     753         265 :     }
     754         265 : }
     755             : 
     756           0 : void GDIMetaFile::Move( long nX, long nY, long nDPIX, long nDPIY )
     757             : {
     758           0 :     const Size      aBaseOffset( nX, nY );
     759           0 :     Size            aOffset( aBaseOffset );
     760           0 :     ScopedVclPtrInstance< VirtualDevice > aMapVDev;
     761             : 
     762           0 :     aMapVDev->EnableOutput( false );
     763           0 :     aMapVDev->SetReferenceDevice( nDPIX, nDPIY );
     764           0 :     aMapVDev->SetMapMode( GetPrefMapMode() );
     765             : 
     766           0 :     for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
     767             :     {
     768           0 :         const MetaActionType nType = pAct->GetType();
     769             :         MetaAction* pModAct;
     770             : 
     771           0 :         if( pAct->GetRefCount() > 1 )
     772             :         {
     773           0 :             aList[ nCurrentActionElement ] = pModAct = pAct->Clone();
     774           0 :             pAct->Delete();
     775             :         }
     776             :         else
     777           0 :             pModAct = pAct;
     778             : 
     779           0 :         if( ( MetaActionType::MAPMODE == nType ) ||
     780           0 :             ( MetaActionType::PUSH == nType ) ||
     781             :             ( MetaActionType::POP == nType ) )
     782             :         {
     783           0 :             pModAct->Execute( aMapVDev.get() );
     784           0 :             if( aMapVDev->GetMapMode().GetMapUnit() == MAP_PIXEL )
     785             :             {
     786           0 :                 aOffset = aMapVDev->LogicToPixel( aBaseOffset, GetPrefMapMode() );
     787           0 :                 MapMode aMap( aMapVDev->GetMapMode() );
     788           0 :                 aOffset.Width() = static_cast<long>(aOffset.Width() * (double)aMap.GetScaleX());
     789           0 :                 aOffset.Height() = static_cast<long>(aOffset.Height() * (double)aMap.GetScaleY());
     790             :             }
     791             :             else
     792           0 :                 aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
     793             :         }
     794             : 
     795           0 :         pModAct->Move( aOffset.Width(), aOffset.Height() );
     796           0 :     }
     797           0 : }
     798             : 
     799          27 : void GDIMetaFile::Scale( double fScaleX, double fScaleY )
     800             : {
     801        7340 :     for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
     802             :     {
     803             :         MetaAction* pModAct;
     804             : 
     805        7313 :         if( pAct->GetRefCount() > 1 )
     806             :         {
     807        7313 :             aList[ nCurrentActionElement ] = pModAct = pAct->Clone();
     808        7313 :             pAct->Delete();
     809             :         }
     810             :         else
     811           0 :             pModAct = pAct;
     812             : 
     813        7313 :         pModAct->Scale( fScaleX, fScaleY );
     814             :     }
     815             : 
     816          27 :     aPrefSize.Width() = FRound( aPrefSize.Width() * fScaleX );
     817          27 :     aPrefSize.Height() = FRound( aPrefSize.Height() * fScaleY );
     818          27 : }
     819             : 
     820          27 : void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY )
     821             : {
     822          27 :     Scale( (double) rScaleX, (double) rScaleY );
     823          27 : }
     824             : 
     825           0 : void GDIMetaFile::Clip( const Rectangle& i_rClipRect )
     826             : {
     827           0 :     Rectangle aCurRect( i_rClipRect );
     828           0 :     ScopedVclPtrInstance< VirtualDevice > aMapVDev;
     829             : 
     830           0 :     aMapVDev->EnableOutput( false );
     831           0 :     aMapVDev->SetMapMode( GetPrefMapMode() );
     832             : 
     833           0 :     for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
     834             :     {
     835           0 :         const MetaActionType nType = pAct->GetType();
     836             : 
     837           0 :         if( ( MetaActionType::MAPMODE == nType ) ||
     838           0 :             ( MetaActionType::PUSH == nType ) ||
     839             :             ( MetaActionType::POP == nType ) )
     840             :         {
     841           0 :             pAct->Execute( aMapVDev.get() );
     842           0 :             aCurRect = OutputDevice::LogicToLogic( i_rClipRect, GetPrefMapMode(), aMapVDev->GetMapMode() );
     843             :         }
     844           0 :         else if( nType == MetaActionType::CLIPREGION )
     845             :         {
     846           0 :             MetaClipRegionAction* pOldAct = static_cast<MetaClipRegionAction*>(pAct);
     847           0 :             vcl::Region aNewReg( aCurRect );
     848           0 :             if( pOldAct->IsClipping() )
     849           0 :                 aNewReg.Intersect( pOldAct->GetRegion() );
     850           0 :             MetaClipRegionAction* pNewAct = new MetaClipRegionAction( aNewReg, true );
     851           0 :             aList[ nCurrentActionElement ] = pNewAct;
     852           0 :             pOldAct->Delete();
     853             :         }
     854           0 :     }
     855           0 : }
     856             : 
     857           0 : Point GDIMetaFile::ImplGetRotatedPoint( const Point& rPt, const Point& rRotatePt,
     858             :                                         const Size& rOffset, double fSin, double fCos )
     859             : {
     860           0 :     const long nX = rPt.X() - rRotatePt.X();
     861           0 :     const long nY = rPt.Y() - rRotatePt.Y();
     862             : 
     863           0 :     return Point( FRound( fCos * nX + fSin * nY ) + rRotatePt.X() + rOffset.Width(),
     864           0 :                   -FRound( fSin * nX - fCos * nY ) + rRotatePt.Y() + rOffset.Height() );
     865             : }
     866             : 
     867           0 : Polygon GDIMetaFile::ImplGetRotatedPolygon( const Polygon& rPoly, const Point& rRotatePt,
     868             :                                             const Size& rOffset, double fSin, double fCos )
     869             : {
     870           0 :     Polygon aRet( rPoly );
     871             : 
     872           0 :     aRet.Rotate( rRotatePt, fSin, fCos );
     873           0 :     aRet.Move( rOffset.Width(), rOffset.Height() );
     874             : 
     875           0 :     return aRet;
     876             : }
     877             : 
     878           0 : tools::PolyPolygon GDIMetaFile::ImplGetRotatedPolyPolygon( const tools::PolyPolygon& rPolyPoly, const Point& rRotatePt,
     879             :                                                     const Size& rOffset, double fSin, double fCos )
     880             : {
     881           0 :     tools::PolyPolygon aRet( rPolyPoly );
     882             : 
     883           0 :     aRet.Rotate( rRotatePt, fSin, fCos );
     884           0 :     aRet.Move( rOffset.Width(), rOffset.Height() );
     885             : 
     886           0 :     return aRet;
     887             : }
     888             : 
     889           0 : void GDIMetaFile::ImplAddGradientEx( GDIMetaFile&         rMtf,
     890             :                                      const OutputDevice&  rMapDev,
     891             :                                      const tools::PolyPolygon&   rPolyPoly,
     892             :                                      const Gradient&      rGrad     )
     893             : {
     894             :     // Generate comment, GradientEx and Gradient actions (within DrawGradient)
     895           0 :     ScopedVclPtrInstance< VirtualDevice > aVDev(  rMapDev, 0  );
     896           0 :     aVDev->EnableOutput( false );
     897           0 :     GDIMetaFile aGradMtf;
     898             : 
     899           0 :     aGradMtf.Record( aVDev.get() );
     900           0 :     aVDev->DrawGradient( rPolyPoly, rGrad );
     901           0 :     aGradMtf.Stop();
     902             : 
     903           0 :     size_t i, nAct( aGradMtf.GetActionSize() );
     904           0 :     for( i=0; i < nAct; ++i )
     905             :     {
     906           0 :         MetaAction* pMetaAct = aGradMtf.GetAction( i );
     907           0 :         pMetaAct->Duplicate();
     908           0 :         rMtf.AddAction( pMetaAct );
     909           0 :     }
     910           0 : }
     911             : 
     912           0 : void GDIMetaFile::Rotate( long nAngle10 )
     913             : {
     914           0 :     nAngle10 %= 3600L;
     915           0 :     nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
     916             : 
     917           0 :     if( nAngle10 )
     918             :     {
     919           0 :         GDIMetaFile     aMtf;
     920           0 :         ScopedVclPtrInstance< VirtualDevice > aMapVDev;
     921           0 :         const double    fAngle = F_PI1800 * nAngle10;
     922           0 :         const double    fSin = sin( fAngle );
     923           0 :         const double    fCos = cos( fAngle );
     924           0 :         Rectangle       aRect=Rectangle( Point(), GetPrefSize() );
     925           0 :         Polygon         aPoly( aRect );
     926             : 
     927           0 :         aPoly.Rotate( Point(), fSin, fCos );
     928             : 
     929           0 :         aMapVDev->EnableOutput( false );
     930           0 :         aMapVDev->SetMapMode( GetPrefMapMode() );
     931             : 
     932           0 :         const Rectangle aNewBound( aPoly.GetBoundRect() );
     933             : 
     934           0 :         const Point aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
     935           0 :         const Size  aOffset( -aNewBound.Left(), -aNewBound.Top() );
     936             : 
     937           0 :         Point     aRotAnchor( aOrigin );
     938           0 :         Size      aRotOffset( aOffset );
     939             : 
     940           0 :         for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
     941             :         {
     942           0 :             const MetaActionType nActionType = pAction->GetType();
     943             : 
     944           0 :             switch( nActionType )
     945             :             {
     946             :                 case( MetaActionType::PIXEL ):
     947             :                 {
     948           0 :                     MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
     949           0 :                     aMtf.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
     950           0 :                                                                               pAct->GetColor() ) );
     951             :                 }
     952           0 :                 break;
     953             : 
     954             :                 case( MetaActionType::POINT ):
     955             :                 {
     956           0 :                     MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
     957           0 :                     aMtf.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
     958             :                 }
     959           0 :                 break;
     960             : 
     961             :                 case( MetaActionType::LINE ):
     962             :                 {
     963           0 :                     MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
     964           0 :                     aMtf.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
     965           0 :                                                         ImplGetRotatedPoint( pAct->GetEndPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
     966           0 :                                                         pAct->GetLineInfo() ) );
     967             :                 }
     968           0 :                 break;
     969             : 
     970             :                 case( MetaActionType::RECT ):
     971             :                 {
     972           0 :                     MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
     973           0 :                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
     974             :                 }
     975           0 :                 break;
     976             : 
     977             :                 case( MetaActionType::ROUNDRECT ):
     978             :                 {
     979           0 :                     MetaRoundRectAction*    pAct = static_cast<MetaRoundRectAction*>(pAction);
     980           0 :                     const Polygon           aRoundRectPoly( pAct->GetRect(), pAct->GetHorzRound(), pAct->GetVertRound() );
     981             : 
     982           0 :                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
     983             :                 }
     984           0 :                 break;
     985             : 
     986             :                 case( MetaActionType::ELLIPSE ):
     987             :                 {
     988           0 :                     MetaEllipseAction*      pAct = static_cast<MetaEllipseAction*>(pAction);
     989           0 :                     const Polygon           aEllipsePoly( pAct->GetRect().Center(), pAct->GetRect().GetWidth() >> 1, pAct->GetRect().GetHeight() >> 1 );
     990             : 
     991           0 :                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
     992             :                 }
     993           0 :                 break;
     994             : 
     995             :                 case( MetaActionType::ARC ):
     996             :                 {
     997           0 :                     MetaArcAction*  pAct = static_cast<MetaArcAction*>(pAction);
     998           0 :                     const Polygon   aArcPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_ARC );
     999             : 
    1000           0 :                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
    1001             :                 }
    1002           0 :                 break;
    1003             : 
    1004             :                 case( MetaActionType::PIE ):
    1005             :                 {
    1006           0 :                     MetaPieAction*  pAct = static_cast<MetaPieAction*>(pAction);
    1007           0 :                     const Polygon   aPiePoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_PIE );
    1008             : 
    1009           0 :                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
    1010             :                 }
    1011           0 :                 break;
    1012             : 
    1013             :                 case( MetaActionType::CHORD ):
    1014             :                 {
    1015           0 :                     MetaChordAction*    pAct = static_cast<MetaChordAction*>(pAction);
    1016           0 :                     const Polygon       aChordPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_CHORD );
    1017             : 
    1018           0 :                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
    1019             :                 }
    1020           0 :                 break;
    1021             : 
    1022             :                 case( MetaActionType::POLYLINE ):
    1023             :                 {
    1024           0 :                     MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
    1025           0 :                     aMtf.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->GetLineInfo() ) );
    1026             :                 }
    1027           0 :                 break;
    1028             : 
    1029             :                 case( MetaActionType::POLYGON ):
    1030             :                 {
    1031           0 :                     MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
    1032           0 :                     aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
    1033             :                 }
    1034           0 :                 break;
    1035             : 
    1036             :                 case( MetaActionType::POLYPOLYGON ):
    1037             :                 {
    1038           0 :                     MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
    1039           0 :                     aMtf.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
    1040             :                 }
    1041           0 :                 break;
    1042             : 
    1043             :                 case( MetaActionType::TEXT ):
    1044             :                 {
    1045           0 :                     MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
    1046           0 :                     aMtf.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
    1047           0 :                                                                              pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
    1048             :                 }
    1049           0 :                 break;
    1050             : 
    1051             :                 case( MetaActionType::TEXTARRAY ):
    1052             :                 {
    1053           0 :                     MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
    1054           0 :                     aMtf.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
    1055           0 :                                                                                   pAct->GetText(), pAct->GetDXArray(), pAct->GetIndex(), pAct->GetLen() ) );
    1056             :                 }
    1057           0 :                 break;
    1058             : 
    1059             :                 case( MetaActionType::STRETCHTEXT ):
    1060             :                 {
    1061           0 :                     MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
    1062           0 :                     aMtf.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
    1063           0 :                                                                                     pAct->GetWidth(), pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
    1064             :                 }
    1065           0 :                 break;
    1066             : 
    1067             :                 case( MetaActionType::TEXTLINE ):
    1068             :                 {
    1069           0 :                     MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
    1070           0 :                     aMtf.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
    1071           0 :                                                                                  pAct->GetWidth(), pAct->GetStrikeout(), pAct->GetUnderline(), pAct->GetOverline() ) );
    1072             :                 }
    1073           0 :                 break;
    1074             : 
    1075             :                 case( MetaActionType::BMPSCALE ):
    1076             :                 {
    1077           0 :                     MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
    1078           0 :                     Polygon             aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
    1079           0 :                     Rectangle           aBmpRect( aBmpPoly.GetBoundRect() );
    1080           0 :                     BitmapEx            aBmpEx( pAct->GetBitmap() );
    1081             : 
    1082           0 :                     aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
    1083             :                     aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(),
    1084           0 :                                                               aBmpEx ) );
    1085             :                 }
    1086           0 :                 break;
    1087             : 
    1088             :                 case( MetaActionType::BMPSCALEPART ):
    1089             :                 {
    1090           0 :                     MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
    1091           0 :                     Polygon                 aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
    1092           0 :                     Rectangle               aBmpRect( aBmpPoly.GetBoundRect() );
    1093           0 :                     BitmapEx                aBmpEx( pAct->GetBitmap() );
    1094             : 
    1095           0 :                     aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
    1096           0 :                     aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
    1097             : 
    1098           0 :                     aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
    1099             :                 }
    1100           0 :                 break;
    1101             : 
    1102             :                 case( MetaActionType::BMPEXSCALE ):
    1103             :                 {
    1104           0 :                     MetaBmpExScaleAction*   pAct = static_cast<MetaBmpExScaleAction*>(pAction);
    1105           0 :                     Polygon                 aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
    1106           0 :                     Rectangle               aBmpRect( aBmpPoly.GetBoundRect() );
    1107           0 :                     BitmapEx                aBmpEx( pAct->GetBitmapEx() );
    1108             : 
    1109           0 :                     aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
    1110             : 
    1111           0 :                     aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
    1112             :                 }
    1113           0 :                 break;
    1114             : 
    1115             :                 case( MetaActionType::BMPEXSCALEPART ):
    1116             :                 {
    1117           0 :                     MetaBmpExScalePartAction*   pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
    1118           0 :                     Polygon                     aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
    1119           0 :                     Rectangle                   aBmpRect( aBmpPoly.GetBoundRect() );
    1120           0 :                     BitmapEx                    aBmpEx( pAct->GetBitmapEx() );
    1121             : 
    1122           0 :                     aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
    1123           0 :                     aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
    1124             : 
    1125           0 :                     aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
    1126             :                 }
    1127           0 :                 break;
    1128             : 
    1129             :                 case( MetaActionType::GRADIENT ):
    1130             :                 {
    1131           0 :                     MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
    1132             : 
    1133           0 :                     ImplAddGradientEx( aMtf, *aMapVDev.get(),
    1134           0 :                                        ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ),
    1135           0 :                                        pAct->GetGradient() );
    1136             :                 }
    1137           0 :                 break;
    1138             : 
    1139             :                 case( MetaActionType::GRADIENTEX ):
    1140             :                 {
    1141           0 :                     MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
    1142           0 :                     aMtf.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
    1143           0 :                                                               pAct->GetGradient() ) );
    1144             :                 }
    1145           0 :                 break;
    1146             : 
    1147             :                 // Handle gradientex comment block correctly
    1148             :                 case( MetaActionType::COMMENT ):
    1149             :                 {
    1150           0 :                     MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
    1151           0 :                     if( pCommentAct->GetComment() == "XGRAD_SEQ_BEGIN" )
    1152             :                     {
    1153           0 :                         int nBeginComments( 1 );
    1154           0 :                         pAction = NextAction();
    1155             : 
    1156             :                         // skip everything, except gradientex action
    1157           0 :                         while( pAction )
    1158             :                         {
    1159           0 :                             const MetaActionType nType = pAction->GetType();
    1160             : 
    1161           0 :                             if( MetaActionType::GRADIENTEX == nType )
    1162             :                             {
    1163             :                                 // Add rotated gradientex
    1164           0 :                                 MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
    1165           0 :                                 ImplAddGradientEx( aMtf, *aMapVDev.get(),
    1166           0 :                                                    ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
    1167           0 :                                                    pAct->GetGradient() );
    1168             :                             }
    1169           0 :                             else if( MetaActionType::COMMENT == nType)
    1170             :                             {
    1171           0 :                                 MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pAction);
    1172           0 :                                 if( pAct->GetComment() == "XGRAD_SEQ_END" )
    1173             :                                 {
    1174             :                                     // handle nested blocks
    1175           0 :                                     --nBeginComments;
    1176             : 
    1177             :                                     // gradientex comment block: end reached, done.
    1178           0 :                                     if( !nBeginComments )
    1179           0 :                                         break;
    1180             :                                 }
    1181           0 :                                 else if( pAct->GetComment() == "XGRAD_SEQ_BEGIN" )
    1182             :                                 {
    1183             :                                     // handle nested blocks
    1184           0 :                                     ++nBeginComments;
    1185             :                                 }
    1186             : 
    1187             :                             }
    1188             : 
    1189           0 :                             pAction =NextAction();
    1190             :                         }
    1191             :                     }
    1192             :                     else
    1193             :                     {
    1194           0 :                         bool bPathStroke = (pCommentAct->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
    1195           0 :                         if ( bPathStroke || pCommentAct->GetComment() == "XPATHFILL_SEQ_BEGIN" )
    1196             :                         {
    1197           0 :                             if ( pCommentAct->GetDataSize() )
    1198             :                             {
    1199           0 :                                 SvMemoryStream aMemStm( const_cast<sal_uInt8 *>(pCommentAct->GetData()), pCommentAct->GetDataSize(), StreamMode::READ );
    1200           0 :                                 SvMemoryStream aDest;
    1201           0 :                                 if ( bPathStroke )
    1202             :                                 {
    1203           0 :                                     SvtGraphicStroke aStroke;
    1204           0 :                                     ReadSvtGraphicStroke( aMemStm, aStroke );
    1205           0 :                                     Polygon aPath;
    1206           0 :                                     aStroke.getPath( aPath );
    1207           0 :                                     aStroke.setPath( ImplGetRotatedPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
    1208           0 :                                     WriteSvtGraphicStroke( aDest, aStroke );
    1209             :                                     aMtf.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
    1210           0 :                                                         static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
    1211             :                                 }
    1212             :                                 else
    1213             :                                 {
    1214           0 :                                     SvtGraphicFill aFill;
    1215           0 :                                     ReadSvtGraphicFill( aMemStm, aFill );
    1216           0 :                                     tools::PolyPolygon aPath;
    1217           0 :                                     aFill.getPath( aPath );
    1218           0 :                                     aFill.setPath( ImplGetRotatedPolyPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
    1219           0 :                                     WriteSvtGraphicFill( aDest, aFill );
    1220             :                                     aMtf.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
    1221           0 :                                                         static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
    1222           0 :                                 }
    1223             :                             }
    1224             :                         }
    1225           0 :                         else if ( pCommentAct->GetComment() == "XPATHSTROKE_SEQ_END"
    1226           0 :                                || pCommentAct->GetComment() == "XPATHFILL_SEQ_END" )
    1227             :                         {
    1228           0 :                             pAction->Execute( aMapVDev.get() );
    1229           0 :                             pAction->Duplicate();
    1230           0 :                             aMtf.AddAction( pAction );
    1231             :                         }
    1232             :                     }
    1233             :                 }
    1234           0 :                 break;
    1235             : 
    1236             :                 case( MetaActionType::HATCH ):
    1237             :                 {
    1238           0 :                     MetaHatchAction*    pAct = static_cast<MetaHatchAction*>(pAction);
    1239           0 :                     Hatch               aHatch( pAct->GetHatch() );
    1240             : 
    1241           0 :                     aHatch.SetAngle( aHatch.GetAngle() + (sal_uInt16) nAngle10 );
    1242           0 :                     aMtf.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
    1243           0 :                                                                                     aHatch ) );
    1244             :                 }
    1245           0 :                 break;
    1246             : 
    1247             :                 case( MetaActionType::Transparent ):
    1248             :                 {
    1249           0 :                     MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
    1250           0 :                     aMtf.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
    1251           0 :                                                                                           pAct->GetTransparence() ) );
    1252             :                 }
    1253           0 :                 break;
    1254             : 
    1255             :                 case( MetaActionType::FLOATTRANSPARENT ):
    1256             :                 {
    1257           0 :                     MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
    1258           0 :                     GDIMetaFile                 aTransMtf( pAct->GetGDIMetaFile() );
    1259           0 :                     Polygon                     aMtfPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
    1260           0 :                     Rectangle                   aMtfRect( aMtfPoly.GetBoundRect() );
    1261             : 
    1262           0 :                     aTransMtf.Rotate( nAngle10 );
    1263             :                     aMtf.AddAction( new MetaFloatTransparentAction( aTransMtf, aMtfRect.TopLeft(), aMtfRect.GetSize(),
    1264           0 :                                                                     pAct->GetGradient() ) );
    1265             :                 }
    1266           0 :                 break;
    1267             : 
    1268             :                 case( MetaActionType::EPS ):
    1269             :                 {
    1270           0 :                     MetaEPSAction*  pAct = static_cast<MetaEPSAction*>(pAction);
    1271           0 :                     GDIMetaFile     aEPSMtf( pAct->GetSubstitute() );
    1272           0 :                     Polygon         aEPSPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
    1273           0 :                     Rectangle       aEPSRect( aEPSPoly.GetBoundRect() );
    1274             : 
    1275           0 :                     aEPSMtf.Rotate( nAngle10 );
    1276             :                     aMtf.AddAction( new MetaEPSAction( aEPSRect.TopLeft(), aEPSRect.GetSize(),
    1277           0 :                                                        pAct->GetLink(), aEPSMtf ) );
    1278             :                 }
    1279           0 :                 break;
    1280             : 
    1281             :                 case( MetaActionType::CLIPREGION ):
    1282             :                 {
    1283           0 :                     MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
    1284             : 
    1285           0 :                     if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
    1286           0 :                         aMtf.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), true ) );
    1287             :                     else
    1288             :                     {
    1289           0 :                         pAction->Duplicate();
    1290           0 :                         aMtf.AddAction( pAction );
    1291             :                     }
    1292             :                 }
    1293           0 :                 break;
    1294             : 
    1295             :                 case( MetaActionType::ISECTRECTCLIPREGION ):
    1296             :                 {
    1297           0 :                     MetaISectRectClipRegionAction*  pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
    1298             :                     aMtf.AddAction( new MetaISectRegionClipRegionAction(vcl::Region(
    1299           0 :                         ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor,
    1300           0 :                             aRotOffset, fSin, fCos )) ) );
    1301             :                 }
    1302           0 :                 break;
    1303             : 
    1304             :                 case( MetaActionType::ISECTREGIONCLIPREGION ):
    1305             :                 {
    1306           0 :                     MetaISectRegionClipRegionAction*    pAct = static_cast<MetaISectRegionClipRegionAction*>(pAction);
    1307           0 :                     const vcl::Region&                  rRegion = pAct->GetRegion();
    1308             : 
    1309           0 :                     if( rRegion.HasPolyPolygonOrB2DPolyPolygon() )
    1310           0 :                         aMtf.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion.GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) );
    1311             :                     else
    1312             :                     {
    1313           0 :                         pAction->Duplicate();
    1314           0 :                         aMtf.AddAction( pAction );
    1315             :                     }
    1316             :                 }
    1317           0 :                 break;
    1318             : 
    1319             :                 case( MetaActionType::REFPOINT ):
    1320             :                 {
    1321           0 :                     MetaRefPointAction* pAct = static_cast<MetaRefPointAction*>(pAction);
    1322           0 :                     aMtf.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct->GetRefPoint(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->IsSetting() ) );
    1323             :                 }
    1324           0 :                 break;
    1325             : 
    1326             :                 case( MetaActionType::FONT ):
    1327             :                 {
    1328           0 :                     MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
    1329           0 :                     vcl::Font       aFont( pAct->GetFont() );
    1330             : 
    1331           0 :                     aFont.SetOrientation( aFont.GetOrientation() + (sal_uInt16) nAngle10 );
    1332           0 :                     aMtf.AddAction( new MetaFontAction( aFont ) );
    1333             :                 }
    1334           0 :                 break;
    1335             : 
    1336             :                 case( MetaActionType::BMP ):
    1337             :                 case( MetaActionType::BMPEX ):
    1338             :                 case( MetaActionType::MASK ):
    1339             :                 case( MetaActionType::MASKSCALE ):
    1340             :                 case( MetaActionType::MASKSCALEPART ):
    1341             :                 case( MetaActionType::WALLPAPER ):
    1342             :                 case( MetaActionType::TEXTRECT ):
    1343             :                 case( MetaActionType::MOVECLIPREGION ):
    1344             :                 {
    1345             :                     OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
    1346             :                 }
    1347           0 :                 break;
    1348             : 
    1349             :                 default:
    1350             :                 {
    1351           0 :                     pAction->Execute( aMapVDev.get() );
    1352           0 :                     pAction->Duplicate();
    1353           0 :                     aMtf.AddAction( pAction );
    1354             : 
    1355             :                     // update rotation point and offset, if necessary
    1356           0 :                     if( ( MetaActionType::MAPMODE == nActionType ) ||
    1357           0 :                         ( MetaActionType::PUSH == nActionType ) ||
    1358             :                         ( MetaActionType::POP == nActionType ) )
    1359             :                     {
    1360           0 :                         aRotAnchor = OutputDevice::LogicToLogic( aOrigin, aPrefMapMode, aMapVDev->GetMapMode() );
    1361           0 :                         aRotOffset = OutputDevice::LogicToLogic( aOffset, aPrefMapMode, aMapVDev->GetMapMode() );
    1362             :                     }
    1363             :                 }
    1364           0 :                 break;
    1365             :             }
    1366             :         }
    1367             : 
    1368           0 :         aMtf.aPrefMapMode = aPrefMapMode;
    1369           0 :         aMtf.aPrefSize = aNewBound.GetSize();
    1370             : 
    1371           0 :         *this = aMtf;
    1372             :     }
    1373           0 : }
    1374             : 
    1375        2388 : static void ImplActionBounds( Rectangle& o_rOutBounds,
    1376             :                               const Rectangle& i_rInBounds,
    1377             :                               const std::vector<Rectangle>& i_rClipStack,
    1378             :                               Rectangle* o_pHairline )
    1379             : {
    1380        2388 :     Rectangle aBounds( i_rInBounds );
    1381        2388 :     if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() )
    1382        1590 :         aBounds.Intersection( i_rClipStack.back() );
    1383        2388 :     if( ! aBounds.IsEmpty() )
    1384             :     {
    1385        2148 :         if( ! o_rOutBounds.IsEmpty() )
    1386        1978 :             o_rOutBounds.Union( aBounds );
    1387             :         else
    1388         170 :             o_rOutBounds = aBounds;
    1389             : 
    1390        2148 :         if(o_pHairline)
    1391             :         {
    1392           0 :             if( ! o_pHairline->IsEmpty() )
    1393           0 :                 o_pHairline->Union( aBounds );
    1394             :             else
    1395           0 :                 *o_pHairline = aBounds;
    1396             :         }
    1397             :     }
    1398        2388 : }
    1399             : 
    1400         211 : Rectangle GDIMetaFile::GetBoundRect( OutputDevice& i_rReference, Rectangle* pHairline ) const
    1401             : {
    1402         211 :     GDIMetaFile     aMtf;
    1403         422 :     ScopedVclPtrInstance< VirtualDevice > aMapVDev(  i_rReference  );
    1404             : 
    1405         211 :     aMapVDev->EnableOutput( false );
    1406         211 :     aMapVDev->SetMapMode( GetPrefMapMode() );
    1407             : 
    1408         422 :     std::vector<Rectangle> aClipStack( 1, Rectangle() );
    1409         422 :     std::vector<PushFlags> aPushFlagStack;
    1410             : 
    1411         211 :     Rectangle aBound;
    1412             : 
    1413         211 :     if(pHairline)
    1414          82 :         *pHairline = Rectangle();
    1415             : 
    1416         211 :     const sal_uLong nCount(GetActionSize());
    1417             : 
    1418        9001 :     for(sal_uLong a(0); a < nCount; a++)
    1419             :     {
    1420        8790 :         MetaAction* pAction = GetAction(a);
    1421        8790 :         const MetaActionType nActionType = pAction->GetType();
    1422        8790 :         Rectangle* pUseHairline = (pHairline && aMapVDev->IsLineColor()) ? pHairline : 0;
    1423             : 
    1424        8790 :         switch( nActionType )
    1425             :         {
    1426             :         case( MetaActionType::PIXEL ):
    1427             :         {
    1428         104 :             MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
    1429             :             ImplActionBounds( aBound,
    1430         104 :                               Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
    1431         208 :                                        aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
    1432         208 :                              aClipStack, pUseHairline );
    1433             :         }
    1434         104 :         break;
    1435             : 
    1436             :         case( MetaActionType::POINT ):
    1437             :         {
    1438           0 :             MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
    1439             :             ImplActionBounds( aBound,
    1440           0 :                               Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
    1441           0 :                                        aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
    1442           0 :                              aClipStack, pUseHairline );
    1443             :         }
    1444           0 :         break;
    1445             : 
    1446             :         case( MetaActionType::LINE ):
    1447             :         {
    1448         315 :             MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
    1449         315 :             Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() );
    1450         315 :             Rectangle aRect( aP1, aP2 );
    1451         315 :             aRect.Justify();
    1452             : 
    1453         315 :             if(pUseHairline)
    1454             :             {
    1455           0 :                 const LineInfo& rLineInfo = pAct->GetLineInfo();
    1456             : 
    1457           0 :                 if(0 != rLineInfo.GetWidth())
    1458           0 :                     pUseHairline = 0;
    1459             :             }
    1460             : 
    1461         315 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
    1462             :         }
    1463         315 :         break;
    1464             : 
    1465             :         case( MetaActionType::RECT ):
    1466             :         {
    1467         371 :             MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
    1468         371 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
    1469             :         }
    1470         371 :         break;
    1471             : 
    1472             :         case( MetaActionType::ROUNDRECT ):
    1473             :         {
    1474           0 :             MetaRoundRectAction*    pAct = static_cast<MetaRoundRectAction*>(pAction);
    1475           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
    1476             :         }
    1477           0 :         break;
    1478             : 
    1479             :         case( MetaActionType::ELLIPSE ):
    1480             :         {
    1481           0 :             MetaEllipseAction*      pAct = static_cast<MetaEllipseAction*>(pAction);
    1482           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
    1483             :         }
    1484           0 :         break;
    1485             : 
    1486             :         case( MetaActionType::ARC ):
    1487             :         {
    1488           0 :             MetaArcAction*  pAct = static_cast<MetaArcAction*>(pAction);
    1489             :             // FIXME: this is imprecise
    1490             :             // e.g. for small arcs the whole rectangle is WAY too large
    1491           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
    1492             :         }
    1493           0 :         break;
    1494             : 
    1495             :         case( MetaActionType::PIE ):
    1496             :         {
    1497           0 :             MetaPieAction*  pAct = static_cast<MetaPieAction*>(pAction);
    1498             :             // FIXME: this is imprecise
    1499             :             // e.g. for small arcs the whole rectangle is WAY too large
    1500           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
    1501             :         }
    1502           0 :         break;
    1503             : 
    1504             :         case( MetaActionType::CHORD ):
    1505             :         {
    1506           0 :             MetaChordAction*    pAct = static_cast<MetaChordAction*>(pAction);
    1507             :             // FIXME: this is imprecise
    1508             :             // e.g. for small arcs the whole rectangle is WAY too large
    1509           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
    1510             :         }
    1511           0 :         break;
    1512             : 
    1513             :         case( MetaActionType::POLYLINE ):
    1514             :         {
    1515          31 :             MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
    1516          31 :             Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
    1517             : 
    1518          31 :             if(pUseHairline)
    1519             :             {
    1520           0 :                 const LineInfo& rLineInfo = pAct->GetLineInfo();
    1521             : 
    1522           0 :                 if(0 != rLineInfo.GetWidth())
    1523           0 :                     pUseHairline = 0;
    1524             :             }
    1525             : 
    1526          31 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
    1527             :         }
    1528          31 :         break;
    1529             : 
    1530             :         case( MetaActionType::POLYGON ):
    1531             :         {
    1532         334 :             MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
    1533         334 :             Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
    1534         334 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
    1535             :         }
    1536         334 :         break;
    1537             : 
    1538             :         case( MetaActionType::POLYPOLYGON ):
    1539             :         {
    1540         323 :             MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
    1541         323 :             Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
    1542         323 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
    1543             :         }
    1544         323 :         break;
    1545             : 
    1546             :         case( MetaActionType::TEXT ):
    1547             :         {
    1548         557 :             MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
    1549         557 :             Rectangle aRect;
    1550             :             // hdu said base = index
    1551         557 :             aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() );
    1552         557 :             Point aPt( pAct->GetPoint() );
    1553         557 :             aRect.Move( aPt.X(), aPt.Y() );
    1554         557 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1555             :         }
    1556         557 :         break;
    1557             : 
    1558             :         case( MetaActionType::TEXTARRAY ):
    1559             :         {
    1560         255 :             MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
    1561         255 :             Rectangle aRect;
    1562             :             // hdu said base = index
    1563         255 :             aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
    1564         510 :                                        0, pAct->GetDXArray() );
    1565         255 :             Point aPt( pAct->GetPoint() );
    1566         255 :             aRect.Move( aPt.X(), aPt.Y() );
    1567         255 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1568             :         }
    1569         255 :         break;
    1570             : 
    1571             :         case( MetaActionType::STRETCHTEXT ):
    1572             :         {
    1573           0 :             MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
    1574           0 :             Rectangle aRect;
    1575             :             // hdu said base = index
    1576           0 :             aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
    1577           0 :                                        pAct->GetWidth(), NULL );
    1578           0 :             Point aPt( pAct->GetPoint() );
    1579           0 :             aRect.Move( aPt.X(), aPt.Y() );
    1580           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1581             :         }
    1582           0 :         break;
    1583             : 
    1584             :         case( MetaActionType::TEXTLINE ):
    1585             :         {
    1586           0 :             MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
    1587             :             // measure a test string to get ascend and descent right
    1588             :             static const sal_Unicode pStr[] = { 0xc4, 0x67, 0 };
    1589           0 :             OUString aStr( pStr );
    1590             : 
    1591           0 :             Rectangle aRect;
    1592           0 :             aMapVDev->GetTextBoundRect( aRect, aStr, 0, 0, aStr.getLength(), 0, NULL );
    1593           0 :             Point aPt( pAct->GetStartPoint() );
    1594           0 :             aRect.Move( aPt.X(), aPt.Y() );
    1595           0 :             aRect.Right() = aRect.Left() + pAct->GetWidth();
    1596           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1597             :         }
    1598           0 :         break;
    1599             : 
    1600             :         case( MetaActionType::BMPSCALE ):
    1601             :         {
    1602          49 :             MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
    1603          49 :             Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
    1604          49 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1605             :         }
    1606          49 :         break;
    1607             : 
    1608             :         case( MetaActionType::BMPSCALEPART ):
    1609             :         {
    1610           0 :             MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
    1611           0 :             Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
    1612           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1613             :         }
    1614           0 :         break;
    1615             : 
    1616             :         case( MetaActionType::BMPEXSCALE ):
    1617             :         {
    1618          49 :             MetaBmpExScaleAction*   pAct = static_cast<MetaBmpExScaleAction*>(pAction);
    1619          49 :             Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
    1620          49 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1621             :         }
    1622          49 :         break;
    1623             : 
    1624             :         case( MetaActionType::BMPEXSCALEPART ):
    1625             :         {
    1626           0 :             MetaBmpExScalePartAction*   pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
    1627           0 :             Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
    1628           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1629             :         }
    1630           0 :         break;
    1631             : 
    1632             :         case( MetaActionType::GRADIENT ):
    1633             :         {
    1634           0 :             MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
    1635           0 :             Rectangle aRect( pAct->GetRect() );
    1636           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1637             :         }
    1638           0 :         break;
    1639             : 
    1640             :         case( MetaActionType::GRADIENTEX ):
    1641             :         {
    1642           0 :             MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
    1643           0 :             Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
    1644           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1645             :         }
    1646           0 :         break;
    1647             : 
    1648             :         case( MetaActionType::COMMENT ):
    1649             :         {
    1650             :             // nothing to do
    1651             :         };
    1652         445 :         break;
    1653             : 
    1654             :         case( MetaActionType::HATCH ):
    1655             :         {
    1656           0 :             MetaHatchAction*    pAct = static_cast<MetaHatchAction*>(pAction);
    1657           0 :             Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
    1658           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1659             :         }
    1660           0 :         break;
    1661             : 
    1662             :         case( MetaActionType::Transparent ):
    1663             :         {
    1664           0 :             MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
    1665           0 :             Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
    1666           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1667             :         }
    1668           0 :         break;
    1669             : 
    1670             :         case( MetaActionType::FLOATTRANSPARENT ):
    1671             :         {
    1672           0 :             MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
    1673             :             // MetaFloatTransparentAction is defined limiting it's content Metafile
    1674             :             // to it's geometry definition(Point, Size), so use these directly
    1675           0 :             const Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
    1676           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1677             :         }
    1678           0 :         break;
    1679             : 
    1680             :         case( MetaActionType::EPS ):
    1681             :         {
    1682           0 :             MetaEPSAction*  pAct = static_cast<MetaEPSAction*>(pAction);
    1683           0 :             Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
    1684           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1685             :         }
    1686           0 :         break;
    1687             : 
    1688             :         case( MetaActionType::CLIPREGION ):
    1689             :         {
    1690         142 :             MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
    1691         142 :             if( pAct->IsClipping() )
    1692         107 :                 aClipStack.back() = OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() );
    1693             :             else
    1694          35 :                 aClipStack.back() = Rectangle();
    1695             :         }
    1696         142 :         break;
    1697             : 
    1698             :         case( MetaActionType::ISECTRECTCLIPREGION ):
    1699             :         {
    1700          38 :             MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
    1701          38 :             Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
    1702          38 :             if( aClipStack.back().IsEmpty() )
    1703          38 :                 aClipStack.back() = aRect;
    1704             :             else
    1705           0 :                 aClipStack.back().Intersection( aRect );
    1706             :         }
    1707          38 :         break;
    1708             : 
    1709             :         case( MetaActionType::ISECTREGIONCLIPREGION ):
    1710             :         {
    1711           6 :             MetaISectRegionClipRegionAction*    pAct = static_cast<MetaISectRegionClipRegionAction*>(pAction);
    1712           6 :             Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
    1713           6 :             if( aClipStack.back().IsEmpty() )
    1714           6 :                 aClipStack.back() = aRect;
    1715             :             else
    1716           0 :                 aClipStack.back().Intersection( aRect );
    1717             :         }
    1718           6 :         break;
    1719             : 
    1720             :         case( MetaActionType::BMP ):
    1721             :         {
    1722           0 :             MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pAction);
    1723           0 :             Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
    1724           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1725             :         }
    1726           0 :         break;
    1727             : 
    1728             :         case( MetaActionType::BMPEX ):
    1729             :         {
    1730           0 :             MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pAction);
    1731           0 :             Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) );
    1732           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1733             :         }
    1734           0 :         break;
    1735             : 
    1736             :         case( MetaActionType::MASK ):
    1737             :         {
    1738           0 :             MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pAction);
    1739           0 :             Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
    1740           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1741             :         }
    1742           0 :         break;
    1743             : 
    1744             :         case( MetaActionType::MASKSCALE ):
    1745             :         {
    1746           0 :             MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
    1747           0 :             Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
    1748           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1749             :         }
    1750           0 :         break;
    1751             : 
    1752             :         case( MetaActionType::MASKSCALEPART ):
    1753             :         {
    1754           0 :             MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
    1755           0 :             Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
    1756           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1757             :         }
    1758           0 :         break;
    1759             : 
    1760             :         case( MetaActionType::WALLPAPER ):
    1761             :         {
    1762           0 :             MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
    1763           0 :             Rectangle aRect( pAct->GetRect() );
    1764           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1765             :         }
    1766           0 :         break;
    1767             : 
    1768             :         case( MetaActionType::TEXTRECT ):
    1769             :         {
    1770           0 :             MetaTextRectAction* pAct = static_cast<MetaTextRectAction*>(pAction);
    1771           0 :             Rectangle aRect( pAct->GetRect() );
    1772           0 :             ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
    1773             :         }
    1774           0 :         break;
    1775             : 
    1776             :         case( MetaActionType::MOVECLIPREGION ):
    1777             :         {
    1778           0 :             MetaMoveClipRegionAction* pAct = static_cast<MetaMoveClipRegionAction*>(pAction);
    1779           0 :             if( ! aClipStack.back().IsEmpty() )
    1780             :             {
    1781           0 :                 Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() );
    1782           0 :                 aDelta = OutputDevice::LogicToLogic( aDelta, aMapVDev->GetMapMode(), GetPrefMapMode() );
    1783           0 :                 aClipStack.back().Move( aDelta.Width(), aDelta.Width() );
    1784             :             }
    1785             :         }
    1786           0 :         break;
    1787             : 
    1788             :         default:
    1789             :             {
    1790        5771 :                 pAction->Execute( aMapVDev.get() );
    1791             : 
    1792        5771 :                 if( nActionType == MetaActionType::PUSH )
    1793             :                 {
    1794         361 :                     MetaPushAction* pAct = static_cast<MetaPushAction*>(pAction);
    1795         361 :                     aPushFlagStack.push_back( pAct->GetFlags() );
    1796         361 :                     if( aPushFlagStack.back() & PushFlags::CLIPREGION )
    1797             :                     {
    1798         342 :                         Rectangle aRect( aClipStack.back() );
    1799         342 :                         aClipStack.push_back( aRect );
    1800             :                     }
    1801             :                 }
    1802        5410 :                 else if( nActionType == MetaActionType::POP )
    1803             :                 {
    1804             :                     // sanity check
    1805         361 :                     if( ! aPushFlagStack.empty() )
    1806             :                     {
    1807         361 :                         if( aPushFlagStack.back() & PushFlags::CLIPREGION )
    1808             :                         {
    1809         342 :                             if( aClipStack.size() > 1 )
    1810         342 :                                 aClipStack.pop_back();
    1811             :                         }
    1812         361 :                         aPushFlagStack.pop_back();
    1813             :                     }
    1814             :                 }
    1815             :             }
    1816        5771 :             break;
    1817             :         }
    1818             :     }
    1819         422 :     return aBound;
    1820             : }
    1821             : 
    1822           0 : Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
    1823             : {
    1824           0 :     return Color( rColor.GetTransparency(),
    1825           0 :                   static_cast<const ImplColAdjustParam*>(pColParam)->pMapR[ rColor.GetRed() ],
    1826           0 :                   static_cast<const ImplColAdjustParam*>(pColParam)->pMapG[ rColor.GetGreen() ],
    1827           0 :                   static_cast<const ImplColAdjustParam*>(pColParam)->pMapB[ rColor.GetBlue() ] );
    1828             : 
    1829             : }
    1830             : 
    1831           0 : BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
    1832             : {
    1833           0 :     const ImplBmpAdjustParam*   p = static_cast<const ImplBmpAdjustParam*>(pBmpParam);
    1834           0 :     BitmapEx                    aRet( rBmpEx );
    1835             : 
    1836             :     aRet.Adjust( p->nLuminancePercent, p->nContrastPercent,
    1837             :                  p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent,
    1838           0 :                  p->fGamma, p->bInvert );
    1839             : 
    1840           0 :     return aRet;
    1841             : }
    1842             : 
    1843           0 : Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam )
    1844             : {
    1845           0 :     sal_uInt8 cLum = rColor.GetLuminance();
    1846             : 
    1847           0 :     if( MTF_CONVERSION_1BIT_THRESHOLD == static_cast<const ImplColConvertParam*>(pColParam)->eConversion )
    1848           0 :         cLum = ( cLum < 128 ) ? 0 : 255;
    1849             : 
    1850           0 :     return Color( rColor.GetTransparency(), cLum, cLum, cLum );
    1851             : }
    1852             : 
    1853           0 : BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
    1854             : {
    1855           0 :     BitmapEx aRet( rBmpEx );
    1856             : 
    1857           0 :     aRet.Convert( static_cast<const ImplBmpConvertParam*>(pBmpParam)->eConversion );
    1858             : 
    1859           0 :     return aRet;
    1860             : }
    1861             : 
    1862           7 : Color GDIMetaFile::ImplColMonoFnc( const Color&, const void* pColParam )
    1863             : {
    1864           7 :     return static_cast<const ImplColMonoParam*>(pColParam)->aColor;
    1865             : }
    1866             : 
    1867          19 : BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
    1868             : {
    1869          19 :     BitmapPalette aPal( 3 );
    1870             : 
    1871          19 :     aPal[ 0 ] = Color( COL_BLACK );
    1872          19 :     aPal[ 1 ] = Color( COL_WHITE );
    1873          19 :     aPal[ 2 ] = static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor;
    1874             : 
    1875          38 :     Bitmap aBmp( rBmpEx.GetSizePixel(), 4, &aPal );
    1876          19 :     aBmp.Erase( static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor );
    1877             : 
    1878          19 :     if( rBmpEx.IsAlpha() )
    1879           3 :         return BitmapEx( aBmp, rBmpEx.GetAlpha() );
    1880          16 :     else if( rBmpEx.IsTransparent() )
    1881          16 :         return BitmapEx( aBmp, rBmpEx.GetMask() );
    1882             :     else
    1883          19 :         return aBmp;
    1884             : }
    1885             : 
    1886           0 : Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam )
    1887             : {
    1888           0 :     const sal_uLong nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue();
    1889             : 
    1890           0 :     for( sal_uLong i = 0; i < static_cast<const ImplColReplaceParam*>(pColParam)->nCount; i++ )
    1891             :     {
    1892           0 :         if( ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinR[ i ] <= nR ) &&
    1893           0 :             ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxR[ i ] >= nR ) &&
    1894           0 :             ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinG[ i ] <= nG ) &&
    1895           0 :             ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxG[ i ] >= nG ) &&
    1896           0 :             ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinB[ i ] <= nB ) &&
    1897           0 :             ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxB[ i ] >= nB ) )
    1898             :         {
    1899           0 :             return static_cast<const ImplColReplaceParam*>(pColParam)->pDstCols[ i ];
    1900             :         }
    1901             :     }
    1902             : 
    1903           0 :     return rColor;
    1904             : }
    1905             : 
    1906           0 : BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
    1907             : {
    1908           0 :     const ImplBmpReplaceParam*  p = static_cast<const ImplBmpReplaceParam*>(pBmpParam);
    1909           0 :     BitmapEx                    aRet( rBmpEx );
    1910             : 
    1911           0 :     aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount, p->pTols );
    1912             : 
    1913           0 :     return aRet;
    1914             : }
    1915             : 
    1916          41 : void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam,
    1917             :                                       BmpExchangeFnc pFncBmp, const void* pBmpParam )
    1918             : {
    1919          41 :     GDIMetaFile aMtf;
    1920             : 
    1921          41 :     aMtf.aPrefSize = aPrefSize;
    1922          41 :     aMtf.aPrefMapMode = aPrefMapMode;
    1923          41 :     aMtf.bUseCanvas = bUseCanvas;
    1924             : 
    1925         129 :     for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
    1926             :     {
    1927          88 :         const MetaActionType nType = pAction->GetType();
    1928             : 
    1929          88 :         switch( nType )
    1930             :         {
    1931             :             case( MetaActionType::PIXEL ):
    1932             :             {
    1933           0 :                 MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
    1934           0 :                 aMtf.push_back( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ) );
    1935             :             }
    1936           0 :             break;
    1937             : 
    1938             :             case( MetaActionType::LINECOLOR ):
    1939             :             {
    1940           4 :                 MetaLineColorAction* pAct = static_cast<MetaLineColorAction*>(pAction);
    1941             : 
    1942           4 :                 if( !pAct->IsSetting() )
    1943           4 :                     pAct->Duplicate();
    1944             :                 else
    1945           0 :                     pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
    1946             : 
    1947           4 :                 aMtf.push_back( pAct );
    1948             :             }
    1949           4 :             break;
    1950             : 
    1951             :             case( MetaActionType::FILLCOLOR ):
    1952             :             {
    1953           8 :                 MetaFillColorAction* pAct = static_cast<MetaFillColorAction*>(pAction);
    1954             : 
    1955           8 :                 if( !pAct->IsSetting() )
    1956           1 :                     pAct->Duplicate();
    1957             :                 else
    1958           7 :                     pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
    1959             : 
    1960           8 :                 aMtf.push_back( pAct );
    1961             :             }
    1962           8 :             break;
    1963             : 
    1964             :             case( MetaActionType::TEXTCOLOR ):
    1965             :             {
    1966           0 :                 MetaTextColorAction* pAct = static_cast<MetaTextColorAction*>(pAction);
    1967           0 :                 aMtf.push_back( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ) );
    1968             :             }
    1969           0 :             break;
    1970             : 
    1971             :             case( MetaActionType::TEXTFILLCOLOR ):
    1972             :             {
    1973           0 :                 MetaTextFillColorAction* pAct = static_cast<MetaTextFillColorAction*>(pAction);
    1974             : 
    1975           0 :                 if( !pAct->IsSetting() )
    1976           0 :                     pAct->Duplicate();
    1977             :                 else
    1978           0 :                     pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
    1979             : 
    1980           0 :                 aMtf.push_back( pAct );
    1981             :             }
    1982           0 :             break;
    1983             : 
    1984             :             case( MetaActionType::TEXTLINECOLOR ):
    1985             :             {
    1986           0 :                 MetaTextLineColorAction* pAct = static_cast<MetaTextLineColorAction*>(pAction);
    1987             : 
    1988           0 :                 if( !pAct->IsSetting() )
    1989           0 :                     pAct->Duplicate();
    1990             :                 else
    1991           0 :                     pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
    1992             : 
    1993           0 :                 aMtf.push_back( pAct );
    1994             :             }
    1995           0 :             break;
    1996             : 
    1997             :             case( MetaActionType::OVERLINECOLOR ):
    1998             :             {
    1999           0 :                 MetaOverlineColorAction* pAct = static_cast<MetaOverlineColorAction*>(pAction);
    2000             : 
    2001           0 :                 if( !pAct->IsSetting() )
    2002           0 :                     pAct->Duplicate();
    2003             :                 else
    2004           0 :                     pAct = new MetaOverlineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
    2005             : 
    2006           0 :                 aMtf.push_back( pAct );
    2007             :             }
    2008           0 :             break;
    2009             : 
    2010             :             case( MetaActionType::FONT ):
    2011             :             {
    2012           0 :                 MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
    2013           0 :                 vcl::Font       aFont( pAct->GetFont() );
    2014             : 
    2015           0 :                 aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) );
    2016           0 :                 aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) );
    2017           0 :                 aMtf.push_back( new MetaFontAction( aFont ) );
    2018             :             }
    2019           0 :             break;
    2020             : 
    2021             :             case( MetaActionType::WALLPAPER ):
    2022             :             {
    2023           0 :                 MetaWallpaperAction*    pAct = static_cast<MetaWallpaperAction*>(pAction);
    2024           0 :                 Wallpaper               aWall( pAct->GetWallpaper() );
    2025           0 :                 const Rectangle&        rRect = pAct->GetRect();
    2026             : 
    2027           0 :                 aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) );
    2028             : 
    2029           0 :                 if( aWall.IsBitmap() )
    2030           0 :                     aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) );
    2031             : 
    2032           0 :                 if( aWall.IsGradient() )
    2033             :                 {
    2034           0 :                     Gradient aGradient( aWall.GetGradient() );
    2035             : 
    2036           0 :                     aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
    2037           0 :                     aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
    2038           0 :                     aWall.SetGradient( aGradient );
    2039             :                 }
    2040             : 
    2041           0 :                 aMtf.push_back( new MetaWallpaperAction( rRect, aWall ) );
    2042             :             }
    2043           0 :             break;
    2044             : 
    2045             :             case( MetaActionType::BMP ):
    2046             :             case( MetaActionType::BMPEX ):
    2047             :             case( MetaActionType::MASK ):
    2048             :             {
    2049             :                 OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
    2050             :             }
    2051           0 :             break;
    2052             : 
    2053             :             case( MetaActionType::BMPSCALE ):
    2054             :             {
    2055           0 :                 MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
    2056             :                 aMtf.push_back( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(),
    2057           0 :                                     pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ) );
    2058             :             }
    2059           0 :             break;
    2060             : 
    2061             :             case( MetaActionType::BMPSCALEPART ):
    2062             :             {
    2063           0 :                 MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
    2064             :                 aMtf.push_back( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
    2065             :                                                     pAct->GetSrcPoint(), pAct->GetSrcSize(),
    2066           0 :                                                     pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() )
    2067           0 :                                                 );
    2068             :             }
    2069           0 :             break;
    2070             : 
    2071             :             case( MetaActionType::BMPEXSCALE ):
    2072             :             {
    2073          19 :                 MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
    2074             :                 aMtf.push_back( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(),
    2075          38 :                                                           pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
    2076          57 :                                                         );
    2077             :             }
    2078          19 :             break;
    2079             : 
    2080             :             case( MetaActionType::BMPEXSCALEPART ):
    2081             :             {
    2082           0 :                 MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
    2083             :                 aMtf.push_back( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
    2084             :                                                               pAct->GetSrcPoint(), pAct->GetSrcSize(),
    2085           0 :                                                               pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
    2086           0 :                                                             );
    2087             :             }
    2088           0 :             break;
    2089             : 
    2090             :             case( MetaActionType::MASKSCALE ):
    2091             :             {
    2092           0 :                 MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pAction);
    2093             :                 aMtf.push_back( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(),
    2094             :                                                          pAct->GetBitmap(),
    2095           0 :                                                          pFncCol( pAct->GetColor(), pColParam ) )
    2096           0 :                                                        );
    2097             :             }
    2098           0 :             break;
    2099             : 
    2100             :             case( MetaActionType::MASKSCALEPART ):
    2101             :             {
    2102           0 :                 MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
    2103             :                 aMtf.push_back( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
    2104             :                                                              pAct->GetSrcPoint(), pAct->GetSrcSize(),
    2105             :                                                              pAct->GetBitmap(),
    2106           0 :                                                              pFncCol( pAct->GetColor(), pColParam ) )
    2107           0 :                                                            );
    2108             :             }
    2109           0 :             break;
    2110             : 
    2111             :             case( MetaActionType::GRADIENT ):
    2112             :             {
    2113           0 :                 MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
    2114           0 :                 Gradient            aGradient( pAct->GetGradient() );
    2115             : 
    2116           0 :                 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
    2117           0 :                 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
    2118           0 :                 aMtf.push_back( new MetaGradientAction( pAct->GetRect(), aGradient ) );
    2119             :             }
    2120           0 :             break;
    2121             : 
    2122             :             case( MetaActionType::GRADIENTEX ):
    2123             :             {
    2124           0 :                 MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
    2125           0 :                 Gradient              aGradient( pAct->GetGradient() );
    2126             : 
    2127           0 :                 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
    2128           0 :                 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
    2129           0 :                 aMtf.push_back( new MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ) );
    2130             :             }
    2131           0 :             break;
    2132             : 
    2133             :             case( MetaActionType::HATCH ):
    2134             :             {
    2135           0 :                 MetaHatchAction*    pAct = static_cast<MetaHatchAction*>(pAction);
    2136           0 :                 Hatch               aHatch( pAct->GetHatch() );
    2137             : 
    2138           0 :                 aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) );
    2139           0 :                 aMtf.push_back( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ) );
    2140             :             }
    2141           0 :             break;
    2142             : 
    2143             :             case( MetaActionType::FLOATTRANSPARENT ):
    2144             :             {
    2145           0 :                 MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
    2146           0 :                 GDIMetaFile                 aTransMtf( pAct->GetGDIMetaFile() );
    2147             : 
    2148           0 :                 aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
    2149             :                 aMtf.push_back( new MetaFloatTransparentAction( aTransMtf,
    2150             :                                                                 pAct->GetPoint(), pAct->GetSize(),
    2151           0 :                                                                 pAct->GetGradient() )
    2152           0 :                                                               );
    2153             :             }
    2154           0 :             break;
    2155             : 
    2156             :             case( MetaActionType::EPS ):
    2157             :             {
    2158           0 :                 MetaEPSAction*  pAct = static_cast<MetaEPSAction*>(pAction);
    2159           0 :                 GDIMetaFile     aSubst( pAct->GetSubstitute() );
    2160             : 
    2161           0 :                 aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
    2162             :                 aMtf.push_back( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(),
    2163           0 :                                                    pAct->GetLink(), aSubst )
    2164           0 :                                                  );
    2165             :             }
    2166           0 :             break;
    2167             : 
    2168             :             default:
    2169             :             {
    2170          57 :                 pAction->Duplicate();
    2171          57 :                 aMtf.push_back( pAction );
    2172             :             }
    2173          57 :             break;
    2174             :         }
    2175             :     }
    2176             : 
    2177          41 :     *this = aMtf;
    2178          41 : }
    2179             : 
    2180           0 : void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
    2181             :                           short nChannelRPercent, short nChannelGPercent,
    2182             :                           short nChannelBPercent, double fGamma, bool bInvert, bool msoBrightness )
    2183             : {
    2184             :     // nothing to do? => return quickly
    2185           0 :     if( nLuminancePercent || nContrastPercent ||
    2186           0 :         nChannelRPercent || nChannelGPercent || nChannelBPercent ||
    2187           0 :         ( fGamma != 1.0 ) || bInvert )
    2188             :     {
    2189             :         double              fM, fROff, fGOff, fBOff, fOff;
    2190             :         ImplColAdjustParam  aColParam;
    2191             :         ImplBmpAdjustParam  aBmpParam;
    2192             : 
    2193           0 :         aColParam.pMapR = new sal_uInt8[ 256 ];
    2194           0 :         aColParam.pMapG = new sal_uInt8[ 256 ];
    2195           0 :         aColParam.pMapB = new sal_uInt8[ 256 ];
    2196             : 
    2197             :         // calculate slope
    2198           0 :         if( nContrastPercent >= 0 )
    2199           0 :             fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
    2200             :         else
    2201           0 :             fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
    2202             : 
    2203           0 :         if(!msoBrightness)
    2204             :             // total offset = luminance offset + contrast offset
    2205           0 :             fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
    2206             :         else
    2207           0 :             fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55;
    2208             : 
    2209             :         // channel offset = channel offset  + total offset
    2210           0 :         fROff = nChannelRPercent * 2.55 + fOff;
    2211           0 :         fGOff = nChannelGPercent * 2.55 + fOff;
    2212           0 :         fBOff = nChannelBPercent * 2.55 + fOff;
    2213             : 
    2214             :         // calculate gamma value
    2215           0 :         fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
    2216           0 :         const bool bGamma = ( fGamma != 1.0 );
    2217             : 
    2218             :         // create mapping table
    2219           0 :         for( long nX = 0L; nX < 256L; nX++ )
    2220             :         {
    2221           0 :             if(!msoBrightness)
    2222             :             {
    2223           0 :                 aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
    2224           0 :                 aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
    2225           0 :                 aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
    2226             :             }
    2227             :             else
    2228             :             {
    2229           0 :                 aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0L, 255L );
    2230           0 :                 aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0L, 255L );
    2231           0 :                 aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0L, 255L );
    2232             :             }
    2233           0 :             if( bGamma )
    2234             :             {
    2235           0 :                 aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma );
    2236           0 :                 aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma );
    2237           0 :                 aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma );
    2238             :             }
    2239             : 
    2240           0 :             if( bInvert )
    2241             :             {
    2242           0 :                 aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ];
    2243           0 :                 aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ];
    2244           0 :                 aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ];
    2245             :             }
    2246             :         }
    2247             : 
    2248           0 :         aBmpParam.nLuminancePercent = nLuminancePercent;
    2249           0 :         aBmpParam.nContrastPercent = nContrastPercent;
    2250           0 :         aBmpParam.nChannelRPercent = nChannelRPercent;
    2251           0 :         aBmpParam.nChannelGPercent = nChannelGPercent;
    2252           0 :         aBmpParam.nChannelBPercent = nChannelBPercent;
    2253           0 :         aBmpParam.fGamma = fGamma;
    2254           0 :         aBmpParam.bInvert = bInvert;
    2255             : 
    2256             :         // do color adjustment
    2257           0 :         ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam );
    2258             : 
    2259           0 :         delete[] aColParam.pMapR;
    2260           0 :         delete[] aColParam.pMapG;
    2261           0 :         delete[] aColParam.pMapB;
    2262             :     }
    2263           0 : }
    2264             : 
    2265           0 : void GDIMetaFile::Convert( MtfConversion eConversion )
    2266             : {
    2267             :     // nothing to do? => return quickly
    2268           0 :     if( eConversion != MTF_CONVERSION_NONE )
    2269             :     {
    2270             :         ImplColConvertParam aColParam;
    2271             :         ImplBmpConvertParam aBmpParam;
    2272             : 
    2273           0 :         aColParam.eConversion = eConversion;
    2274           0 :         aBmpParam.eConversion = ( MTF_CONVERSION_1BIT_THRESHOLD == eConversion ) ? BMP_CONVERSION_1BIT_THRESHOLD : BMP_CONVERSION_8BIT_GREYS;
    2275             : 
    2276           0 :         ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam );
    2277             :     }
    2278           0 : }
    2279             : 
    2280           0 : void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, sal_uLong* pTols )
    2281             : {
    2282             :     ImplColReplaceParam aColParam;
    2283             :     ImplBmpReplaceParam aBmpParam;
    2284             : 
    2285           0 :     aColParam.pMinR = new sal_uLong[ nColorCount ];
    2286           0 :     aColParam.pMaxR = new sal_uLong[ nColorCount ];
    2287           0 :     aColParam.pMinG = new sal_uLong[ nColorCount ];
    2288           0 :     aColParam.pMaxG = new sal_uLong[ nColorCount ];
    2289           0 :     aColParam.pMinB = new sal_uLong[ nColorCount ];
    2290           0 :     aColParam.pMaxB = new sal_uLong[ nColorCount ];
    2291             : 
    2292           0 :     for( sal_uLong i = 0; i < nColorCount; i++ )
    2293             :     {
    2294           0 :         const long  nTol = pTols ? ( pTols[ i ] * 255 ) / 100 : 0;
    2295             :         long        nVal;
    2296             : 
    2297           0 :         nVal = pSearchColors[ i ].GetRed();
    2298           0 :         aColParam.pMinR[ i ] = (sal_uLong) std::max( nVal - nTol, 0L );
    2299           0 :         aColParam.pMaxR[ i ] = (sal_uLong) std::min( nVal + nTol, 255L );
    2300             : 
    2301           0 :         nVal = pSearchColors[ i ].GetGreen();
    2302           0 :         aColParam.pMinG[ i ] = (sal_uLong) std::max( nVal - nTol, 0L );
    2303           0 :         aColParam.pMaxG[ i ] = (sal_uLong) std::min( nVal + nTol, 255L );
    2304             : 
    2305           0 :         nVal = pSearchColors[ i ].GetBlue();
    2306           0 :         aColParam.pMinB[ i ] = (sal_uLong) std::max( nVal - nTol, 0L );
    2307           0 :         aColParam.pMaxB[ i ] = (sal_uLong) std::min( nVal + nTol, 255L );
    2308             :     }
    2309             : 
    2310           0 :     aColParam.pDstCols = pReplaceColors;
    2311           0 :     aColParam.nCount = nColorCount;
    2312             : 
    2313           0 :     aBmpParam.pSrcCols = pSearchColors;
    2314           0 :     aBmpParam.pDstCols = pReplaceColors;
    2315           0 :     aBmpParam.nCount = nColorCount;
    2316           0 :     aBmpParam.pTols = pTols;
    2317             : 
    2318           0 :     ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam );
    2319             : 
    2320           0 :     delete[] aColParam.pMinR;
    2321           0 :     delete[] aColParam.pMaxR;
    2322           0 :     delete[] aColParam.pMinG;
    2323           0 :     delete[] aColParam.pMaxG;
    2324           0 :     delete[] aColParam.pMinB;
    2325           0 :     delete[] aColParam.pMaxB;
    2326           0 : };
    2327             : 
    2328          41 : GDIMetaFile GDIMetaFile::GetMonochromeMtf( const Color& rColor ) const
    2329             : {
    2330          41 :     GDIMetaFile aRet( *this );
    2331             : 
    2332          41 :     ImplColMonoParam    aColParam;
    2333          41 :     ImplBmpMonoParam    aBmpParam;
    2334             : 
    2335          41 :     aColParam.aColor = rColor;
    2336          41 :     aBmpParam.aColor = rColor;
    2337             : 
    2338          41 :     aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam );
    2339             : 
    2340          41 :     return aRet;
    2341             : }
    2342             : 
    2343         834 : sal_uLong GDIMetaFile::GetChecksum() const
    2344             : {
    2345         834 :     GDIMetaFile         aMtf;
    2346        1668 :     SvMemoryStream      aMemStm( 65535, 65535 );
    2347         834 :     ImplMetaWriteData   aWriteData;
    2348             :     SVBT16              aBT16;
    2349             :     SVBT32              aBT32;
    2350         834 :     sal_uLong               nCrc = 0;
    2351             : 
    2352         834 :     aWriteData.meActualCharSet = aMemStm.GetStreamCharSet();
    2353       72991 :     for( size_t i = 0, nObjCount = GetActionSize(); i < nObjCount; i++ )
    2354             :     {
    2355       72157 :         MetaAction* pAction = GetAction( i );
    2356             : 
    2357       72157 :         switch( pAction->GetType() )
    2358             :         {
    2359             :             case( MetaActionType::BMP ):
    2360             :             {
    2361           0 :                 MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pAction);
    2362             : 
    2363           0 :                 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
    2364           0 :                 nCrc = rtl_crc32( nCrc, aBT16, 2 );
    2365             : 
    2366           0 :                 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
    2367           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2368             : 
    2369           0 :                 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
    2370           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2371             : 
    2372           0 :                 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
    2373           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2374             :             }
    2375           0 :             break;
    2376             : 
    2377             :             case( MetaActionType::BMPSCALE ):
    2378             :             {
    2379         389 :                 MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
    2380             : 
    2381         389 :                 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
    2382         389 :                 nCrc = rtl_crc32( nCrc, aBT16, 2 );
    2383             : 
    2384         389 :                 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
    2385         389 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2386             : 
    2387         389 :                 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
    2388         389 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2389             : 
    2390         389 :                 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
    2391         389 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2392             : 
    2393         389 :                 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
    2394         389 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2395             : 
    2396         389 :                 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
    2397         389 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2398             :             }
    2399         389 :             break;
    2400             : 
    2401             :             case( MetaActionType::BMPSCALEPART ):
    2402             :             {
    2403           0 :                 MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
    2404             : 
    2405           0 :                 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
    2406           0 :                 nCrc = rtl_crc32( nCrc, aBT16, 2 );
    2407             : 
    2408           0 :                 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
    2409           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2410             : 
    2411           0 :                 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
    2412           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2413             : 
    2414           0 :                 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
    2415           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2416             : 
    2417           0 :                 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
    2418           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2419             : 
    2420           0 :                 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
    2421           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2422             : 
    2423           0 :                 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
    2424           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2425             : 
    2426           0 :                 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
    2427           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2428             : 
    2429           0 :                 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
    2430           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2431             : 
    2432           0 :                 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
    2433           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2434             :             }
    2435           0 :             break;
    2436             : 
    2437             :             case( MetaActionType::BMPEX ):
    2438             :             {
    2439           4 :                 MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pAction);
    2440             : 
    2441           4 :                 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
    2442           4 :                 nCrc = rtl_crc32( nCrc, aBT16, 2 );
    2443             : 
    2444           4 :                 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
    2445           4 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2446             : 
    2447           4 :                 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
    2448           4 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2449             : 
    2450           4 :                 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
    2451           4 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2452             :             }
    2453           4 :             break;
    2454             : 
    2455             :             case( MetaActionType::BMPEXSCALE ):
    2456             :             {
    2457          51 :                 MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
    2458             : 
    2459          51 :                 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
    2460          51 :                 nCrc = rtl_crc32( nCrc, aBT16, 2 );
    2461             : 
    2462          51 :                 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
    2463          51 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2464             : 
    2465          51 :                 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
    2466          51 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2467             : 
    2468          51 :                 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
    2469          51 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2470             : 
    2471          51 :                 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
    2472          51 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2473             : 
    2474          51 :                 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
    2475          51 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2476             :             }
    2477          51 :             break;
    2478             : 
    2479             :             case( MetaActionType::BMPEXSCALEPART ):
    2480             :             {
    2481           0 :                 MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
    2482             : 
    2483           0 :                 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
    2484           0 :                 nCrc = rtl_crc32( nCrc, aBT16, 2 );
    2485             : 
    2486           0 :                 UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
    2487           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2488             : 
    2489           0 :                 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
    2490           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2491             : 
    2492           0 :                 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
    2493           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2494             : 
    2495           0 :                 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
    2496           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2497             : 
    2498           0 :                 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
    2499           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2500             : 
    2501           0 :                 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
    2502           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2503             : 
    2504           0 :                 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
    2505           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2506             : 
    2507           0 :                 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
    2508           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2509             : 
    2510           0 :                 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
    2511           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2512             :             }
    2513           0 :             break;
    2514             : 
    2515             :             case( MetaActionType::MASK ):
    2516             :             {
    2517           0 :                 MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pAction);
    2518             : 
    2519           0 :                 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
    2520           0 :                 nCrc = rtl_crc32( nCrc, aBT16, 2 );
    2521             : 
    2522           0 :                 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
    2523           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2524             : 
    2525           0 :                 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
    2526           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2527             : 
    2528           0 :                 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
    2529           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2530             : 
    2531           0 :                 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
    2532           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2533             :             }
    2534           0 :             break;
    2535             : 
    2536             :             case( MetaActionType::MASKSCALE ):
    2537             :             {
    2538           0 :                 MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pAction);
    2539             : 
    2540           0 :                 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
    2541           0 :                 nCrc = rtl_crc32( nCrc, aBT16, 2 );
    2542             : 
    2543           0 :                 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
    2544           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2545             : 
    2546           0 :                 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
    2547           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2548             : 
    2549           0 :                 UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
    2550           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2551             : 
    2552           0 :                 UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
    2553           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2554             : 
    2555           0 :                 UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
    2556           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2557             : 
    2558           0 :                 UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
    2559           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2560             :             }
    2561           0 :             break;
    2562             : 
    2563             :             case( MetaActionType::MASKSCALEPART ):
    2564             :             {
    2565           0 :                 MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
    2566             : 
    2567           0 :                 ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
    2568           0 :                 nCrc = rtl_crc32( nCrc, aBT16, 2 );
    2569             : 
    2570           0 :                 UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
    2571           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2572             : 
    2573           0 :                 UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
    2574           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2575             : 
    2576           0 :                 UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
    2577           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2578             : 
    2579           0 :                 UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
    2580           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2581             : 
    2582           0 :                 UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
    2583           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2584             : 
    2585           0 :                 UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
    2586           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2587             : 
    2588           0 :                 UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
    2589           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2590             : 
    2591           0 :                 UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
    2592           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2593             : 
    2594           0 :                 UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
    2595           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2596             : 
    2597           0 :                 UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
    2598           0 :                 nCrc = rtl_crc32( nCrc, aBT32, 4 );
    2599             :             }
    2600           0 :             break;
    2601             : 
    2602             :             case MetaActionType::EPS :
    2603             :             {
    2604           0 :                 MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
    2605           0 :                 nCrc = rtl_crc32( nCrc, pAct->GetLink().GetData(), pAct->GetLink().GetDataSize() );
    2606             :             }
    2607           0 :             break;
    2608             : 
    2609             :             case MetaActionType::CLIPREGION :
    2610             :             {
    2611         632 :                 MetaClipRegionAction& rAct = static_cast<MetaClipRegionAction&>(*pAction);
    2612         632 :                 const vcl::Region& rRegion = rAct.GetRegion();
    2613             : 
    2614         632 :                 if(rRegion.HasPolyPolygonOrB2DPolyPolygon())
    2615             :                 {
    2616             :                     // It has shown that this is a possible bottleneck for checksum calculation.
    2617             :                     // In worst case a very expensive RegionHandle representation gets created.
    2618             :                     // In this case it's cheaper to use the PolyPolygon
    2619          84 :                     const basegfx::B2DPolyPolygon aPolyPolygon(rRegion.GetAsB2DPolyPolygon());
    2620          84 :                     const sal_uInt32 nPolyCount(aPolyPolygon.count());
    2621             :                     SVBT64 aSVBT64;
    2622             : 
    2623         336 :                     for(sal_uInt32 a(0); a < nPolyCount; a++)
    2624             :                     {
    2625         252 :                         const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(a));
    2626         252 :                         const sal_uInt32 nPointCount(aPolygon.count());
    2627         252 :                         const bool bControl(aPolygon.areControlPointsUsed());
    2628             : 
    2629       11046 :                         for(sal_uInt32 b(0); b < nPointCount; b++)
    2630             :                         {
    2631       10794 :                             const basegfx::B2DPoint aPoint(aPolygon.getB2DPoint(b));
    2632             : 
    2633       10794 :                             DoubleToSVBT64(aPoint.getX(), aSVBT64);
    2634       10794 :                             nCrc = rtl_crc32(nCrc, aSVBT64, 8);
    2635       10794 :                             DoubleToSVBT64(aPoint.getY(), aSVBT64);
    2636       10794 :                             nCrc = rtl_crc32(nCrc, aSVBT64, 8);
    2637             : 
    2638       10794 :                             if(bControl)
    2639             :                             {
    2640           0 :                                 if(aPolygon.isPrevControlPointUsed(b))
    2641             :                                 {
    2642           0 :                                     const basegfx::B2DPoint aCtrl(aPolygon.getPrevControlPoint(b));
    2643             : 
    2644           0 :                                     DoubleToSVBT64(aCtrl.getX(), aSVBT64);
    2645           0 :                                     nCrc = rtl_crc32(nCrc, aSVBT64, 8);
    2646           0 :                                     DoubleToSVBT64(aCtrl.getY(), aSVBT64);
    2647           0 :                                     nCrc = rtl_crc32(nCrc, aSVBT64, 8);
    2648             :                                 }
    2649             : 
    2650           0 :                                 if(aPolygon.isNextControlPointUsed(b))
    2651             :                                 {
    2652           0 :                                     const basegfx::B2DPoint aCtrl(aPolygon.getNextControlPoint(b));
    2653             : 
    2654           0 :                                     DoubleToSVBT64(aCtrl.getX(), aSVBT64);
    2655           0 :                                     nCrc = rtl_crc32(nCrc, aSVBT64, 8);
    2656           0 :                                     DoubleToSVBT64(aCtrl.getY(), aSVBT64);
    2657           0 :                                     nCrc = rtl_crc32(nCrc, aSVBT64, 8);
    2658             :                                 }
    2659             :                             }
    2660       10794 :                         }
    2661         252 :                     }
    2662             : 
    2663          84 :                     sal_uInt8 tmp = (sal_uInt8)rAct.IsClipping();
    2664          84 :                     nCrc = rtl_crc32(nCrc, &tmp, 1);
    2665             :                 }
    2666             :                 else
    2667             :                 {
    2668         548 :                     pAction->Write( aMemStm, &aWriteData );
    2669         548 :                     nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() );
    2670         548 :                     aMemStm.Seek( 0 );
    2671             :                 }
    2672             :             }
    2673         632 :             break;
    2674             : 
    2675             :             default:
    2676             :             {
    2677       71081 :                 pAction->Write( aMemStm, &aWriteData );
    2678       71081 :                 nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() );
    2679       71081 :                 aMemStm.Seek( 0 );
    2680             :             }
    2681       71081 :             break;
    2682             :         }
    2683             :     }
    2684             : 
    2685        1668 :     return nCrc;
    2686             : }
    2687             : 
    2688        1623 : sal_uLong GDIMetaFile::GetSizeBytes() const
    2689             : {
    2690        1623 :     sal_uLong nSizeBytes = 0;
    2691             : 
    2692      142254 :     for( size_t i = 0, nObjCount = GetActionSize(); i < nObjCount; ++i )
    2693             :     {
    2694      140631 :         MetaAction* pAction = GetAction( i );
    2695             : 
    2696             :         // default action size is set to 32 (=> not the exact value)
    2697      140631 :         nSizeBytes += 32;
    2698             : 
    2699             :         // add sizes for large action content
    2700      140631 :         switch( pAction->GetType() )
    2701             :         {
    2702           0 :             case( MetaActionType::BMP ): nSizeBytes += static_cast<MetaBmpAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
    2703         837 :             case( MetaActionType::BMPSCALE ): nSizeBytes += static_cast<MetaBmpScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
    2704           0 :             case( MetaActionType::BMPSCALEPART ): nSizeBytes += static_cast<MetaBmpScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
    2705             : 
    2706           4 :             case( MetaActionType::BMPEX ): nSizeBytes += static_cast<MetaBmpExAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
    2707         102 :             case( MetaActionType::BMPEXSCALE ): nSizeBytes += static_cast<MetaBmpExScaleAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
    2708           0 :             case( MetaActionType::BMPEXSCALEPART ): nSizeBytes += static_cast<MetaBmpExScalePartAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
    2709             : 
    2710           0 :             case( MetaActionType::MASK ): nSizeBytes += static_cast<MetaMaskAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
    2711           0 :             case( MetaActionType::MASKSCALE ): nSizeBytes += static_cast<MetaMaskScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
    2712           0 :             case( MetaActionType::MASKSCALEPART ): nSizeBytes += static_cast<MetaMaskScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
    2713             : 
    2714        1409 :             case( MetaActionType::POLYLINE ): nSizeBytes += static_cast<MetaPolyLineAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
    2715        2610 :             case( MetaActionType::POLYGON ): nSizeBytes += static_cast<MetaPolygonAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
    2716             :             case( MetaActionType::POLYPOLYGON ):
    2717             :             {
    2718        3619 :                 const tools::PolyPolygon& rPolyPoly = static_cast<MetaPolyPolygonAction*>( pAction )->GetPolyPolygon();
    2719             : 
    2720        9570 :                 for( sal_uInt16 n = 0; n < rPolyPoly.Count(); ++n )
    2721        5951 :                     nSizeBytes += ( rPolyPoly[ n ].GetSize() * sizeof( Point ) );
    2722             :             }
    2723        3619 :             break;
    2724             : 
    2725        6155 :             case( MetaActionType::TEXT ): nSizeBytes += static_cast<MetaTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
    2726           0 :             case( MetaActionType::STRETCHTEXT ): nSizeBytes += static_cast<MetaStretchTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
    2727           0 :             case( MetaActionType::TEXTRECT ): nSizeBytes += static_cast<MetaTextRectAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
    2728             :             case( MetaActionType::TEXTARRAY ):
    2729             :             {
    2730        8700 :                 MetaTextArrayAction* pTextArrayAction = static_cast<MetaTextArrayAction*>(pAction);
    2731             : 
    2732        8700 :                 nSizeBytes += ( pTextArrayAction->GetText().getLength() * sizeof( sal_Unicode ) );
    2733             : 
    2734        8700 :                 if( pTextArrayAction->GetDXArray() )
    2735        8700 :                     nSizeBytes += ( pTextArrayAction->GetLen() << 2 );
    2736             :             }
    2737        8700 :             break;
    2738      117195 :             default: break;
    2739             :         }
    2740             :     }
    2741             : 
    2742        1623 :     return nSizeBytes;
    2743             : }
    2744             : 
    2745        4966 : SvStream& ReadGDIMetaFile( SvStream& rIStm, GDIMetaFile& rGDIMetaFile )
    2746             : {
    2747        4966 :     if( !rIStm.GetError() )
    2748             :     {
    2749             :         char    aId[ 7 ];
    2750        4966 :         sal_uLong      nStmPos = rIStm.Tell();
    2751        4966 :         SvStreamEndian nOldFormat = rIStm.GetEndian();
    2752             : 
    2753        4966 :         rIStm.SetEndian( SvStreamEndian::LITTLE );
    2754             : 
    2755        4966 :         aId[ 0 ] = 0;
    2756        4966 :         aId[ 6 ] = 0;
    2757        4966 :         rIStm.Read( aId, 6 );
    2758             : 
    2759        4966 :         if ( !strcmp( aId, "VCLMTF" ) )
    2760             :         {
    2761             :             // new format
    2762             :             VersionCompat* pCompat;
    2763             :             MetaAction*    pAction;
    2764        4957 :             sal_uInt32     nStmCompressMode = 0;
    2765        4957 :             sal_uInt32     nCount = 0;
    2766             : 
    2767        4957 :             pCompat = new VersionCompat( rIStm, StreamMode::READ );
    2768             : 
    2769        4957 :             rIStm.ReadUInt32( nStmCompressMode );
    2770        4957 :             ReadMapMode( rIStm, rGDIMetaFile.aPrefMapMode );
    2771        4957 :             ReadPair( rIStm, rGDIMetaFile.aPrefSize );
    2772        4957 :             rIStm.ReadUInt32( nCount );
    2773             : 
    2774        4957 :             delete pCompat;
    2775             : 
    2776        4957 :             ImplMetaReadData aReadData;
    2777        4957 :             aReadData.meActualCharSet = rIStm.GetStreamCharSet();
    2778             : 
    2779      329502 :             for( sal_uInt32 nAction = 0UL; ( nAction < nCount ) && !rIStm.IsEof(); nAction++ )
    2780             :             {
    2781      324545 :                 pAction = MetaAction::ReadMetaAction( rIStm, &aReadData );
    2782             : 
    2783      324545 :                 if( pAction )
    2784             :                 {
    2785      324545 :                     if (pAction->GetType() == MetaActionType::COMMENT)
    2786             :                     {
    2787        4786 :                         MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
    2788        4786 :                         if ( pCommentAct->GetComment() == "EMF_PLUS" )
    2789           0 :                             rGDIMetaFile.UseCanvas( true );
    2790             :                     }
    2791      324545 :                     rGDIMetaFile.AddAction( pAction );
    2792             :                 }
    2793             :             }
    2794             :         }
    2795             :         else
    2796             :         {
    2797             :             // to avoid possible compiler optimizations => new/delete
    2798           9 :             rIStm.Seek( nStmPos );
    2799           9 :             delete( new SVMConverter( rIStm, rGDIMetaFile, CONVERT_FROM_SVM1 ) );
    2800             :         }
    2801             : 
    2802             :         // check for errors
    2803        4966 :         if( rIStm.GetError() )
    2804             :         {
    2805           9 :             rGDIMetaFile.Clear();
    2806           9 :             rIStm.Seek( nStmPos );
    2807             :         }
    2808             : 
    2809        4966 :         rIStm.SetEndian( nOldFormat );
    2810             :     }
    2811             :     else
    2812             :     {
    2813             :         SAL_WARN("vcl.gdi", "Stream error: " << rIStm.GetError());
    2814             :     }
    2815             : 
    2816        4966 :     return rIStm;
    2817             : }
    2818             : 
    2819         349 : SvStream& WriteGDIMetaFile( SvStream& rOStm, const GDIMetaFile& rGDIMetaFile )
    2820             : {
    2821         349 :     if( !rOStm.GetError() )
    2822             :     {
    2823         349 :         static const char*  pEnableSVM1 = getenv( "SAL_ENABLE_SVM1" );
    2824         349 :         static const bool   bNoSVM1 = (NULL == pEnableSVM1 ) || ( '0' == *pEnableSVM1 );
    2825             : 
    2826         349 :         if( bNoSVM1 || rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50  )
    2827             :         {
    2828         349 :             const_cast< GDIMetaFile& >( rGDIMetaFile ).Write( rOStm );
    2829             :         }
    2830             :         else
    2831             :         {
    2832           0 :             delete( new SVMConverter( rOStm, const_cast< GDIMetaFile& >( rGDIMetaFile ), CONVERT_TO_SVM1 ) );
    2833             :         }
    2834             : 
    2835             : #ifdef DEBUG
    2836             :         if( !bNoSVM1 && rOStm.GetVersion() < SOFFICE_FILEFORMAT_50 )
    2837             :         {
    2838             : OSL_TRACE( \
    2839             : "GDIMetaFile would normally be written in old SVM1 format by this call. \
    2840             : The current implementation always writes in VCLMTF format. \
    2841             : Please set environment variable SAL_ENABLE_SVM1 to '1' to reenable old behavior" );
    2842             :         }
    2843             : #endif // DEBUG
    2844             :     }
    2845             : 
    2846         349 :     return rOStm;
    2847             : }
    2848             : 
    2849           0 : SvStream& GDIMetaFile::Read( SvStream& rIStm )
    2850             : {
    2851           0 :     Clear();
    2852           0 :     ReadGDIMetaFile( rIStm, *this );
    2853             : 
    2854           0 :     return rIStm;
    2855             : }
    2856             : 
    2857        5287 : SvStream& GDIMetaFile::Write( SvStream& rOStm )
    2858             : {
    2859             :     VersionCompat*   pCompat;
    2860        5287 :     const SvStreamCompressFlags nStmCompressMode = rOStm.GetCompressMode();
    2861        5287 :     SvStreamEndian   nOldFormat = rOStm.GetEndian();
    2862             : 
    2863        5287 :     rOStm.SetEndian( SvStreamEndian::LITTLE );
    2864        5287 :     rOStm.Write( "VCLMTF", 6 );
    2865             : 
    2866        5287 :     pCompat = new VersionCompat( rOStm, StreamMode::WRITE, 1 );
    2867             : 
    2868        5287 :     rOStm.WriteUInt32( static_cast<sal_uInt32>(nStmCompressMode) );
    2869        5287 :     WriteMapMode( rOStm, aPrefMapMode );
    2870        5287 :     WritePair( rOStm, aPrefSize );
    2871        5287 :     rOStm.WriteUInt32( GetActionSize() );
    2872             : 
    2873        5287 :     delete pCompat;
    2874             : 
    2875        5287 :     ImplMetaWriteData aWriteData;
    2876             : 
    2877        5287 :     aWriteData.meActualCharSet = rOStm.GetStreamCharSet();
    2878             : 
    2879        5287 :     MetaAction* pAct = FirstAction();
    2880      364347 :     while ( pAct )
    2881             :     {
    2882      353773 :         pAct->Write( rOStm, &aWriteData );
    2883      353773 :         pAct = NextAction();
    2884             :     }
    2885             : 
    2886        5287 :     rOStm.SetEndian( nOldFormat );
    2887             : 
    2888        5287 :     return rOStm;
    2889             : }
    2890             : 
    2891          78 : bool GDIMetaFile::CreateThumbnail(BitmapEx& rBitmapEx, sal_uInt32 nMaximumExtent, BmpConversion eColorConversion, BmpScaleFlag nScaleFlag) const
    2892             : {
    2893             :     // initialization seems to be complicated but is used to avoid rounding errors
    2894          78 :     ScopedVclPtrInstance< VirtualDevice > aVDev;
    2895          78 :     const Point     aNullPt;
    2896          78 :     const Point     aTLPix( aVDev->LogicToPixel( aNullPt, GetPrefMapMode() ) );
    2897          78 :     const Point     aBRPix( aVDev->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
    2898          78 :     Size            aDrawSize( aVDev->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
    2899          78 :     Size            aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 );
    2900             : 
    2901          78 :     if (!rBitmapEx.IsEmpty())
    2902           0 :         rBitmapEx.SetEmpty();
    2903             : 
    2904             :     // determine size that has the same aspect ratio as image size and
    2905             :     // fits into the rectangle determined by nMaximumExtent
    2906         234 :     if ( aSizePix.Width() && aSizePix.Height()
    2907         234 :       && ( sal::static_int_cast< unsigned long >(aSizePix.Width()) >
    2908           0 :                nMaximumExtent ||
    2909           0 :            sal::static_int_cast< unsigned long >(aSizePix.Height()) >
    2910             :                nMaximumExtent ) )
    2911             :     {
    2912          78 :         const Size  aOldSizePix( aSizePix );
    2913          78 :         double      fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height();
    2914             : 
    2915          78 :         if ( fWH <= 1.0 )
    2916             :         {
    2917          73 :             aSizePix.Width() = FRound( nMaximumExtent * fWH );
    2918          73 :             aSizePix.Height() = nMaximumExtent;
    2919             :         }
    2920             :         else
    2921             :         {
    2922           5 :             aSizePix.Width() = nMaximumExtent;
    2923           5 :             aSizePix.Height() = FRound(  nMaximumExtent / fWH );
    2924             :         }
    2925             : 
    2926          78 :         aDrawSize.Width() = FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() );
    2927          78 :         aDrawSize.Height() = FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() );
    2928             :     }
    2929             : 
    2930             :     // draw image(s) into VDev and get resulting image
    2931             :     // do it 4x larger to be able to scale it down & get beautiful antialias
    2932          78 :     Size aAntialiasSize(aSizePix.Width() * 4, aSizePix.Height() * 4);
    2933          78 :     if (aVDev->SetOutputSizePixel(aAntialiasSize))
    2934             :     {
    2935             :         // antialias: provide 4x larger size, and then scale down the result
    2936          78 :         Size aAntialias(aDrawSize.Width() * 4, aDrawSize.Height() * 4);
    2937             : 
    2938             :         // draw metafile into VDev
    2939          78 :         Point aBackPosPix;
    2940          78 :         const_cast<GDIMetaFile *>(this)->WindStart();
    2941          78 :         const_cast<GDIMetaFile *>(this)->Play(aVDev.get(), aBackPosPix, aAntialias);
    2942             : 
    2943             :         // get paint bitmap
    2944          78 :         Bitmap aBitmap( aVDev->GetBitmap( aNullPt, aVDev->GetOutputSizePixel() ) );
    2945             : 
    2946             :         // scale down the image to the desired size - use the input scaler for the scaling operation
    2947          78 :         aBitmap.Scale(aDrawSize, nScaleFlag);
    2948             : 
    2949             :         // convert to desired bitmap color format
    2950          78 :         aBitmap.Convert(eColorConversion);
    2951             : 
    2952          78 :         rBitmapEx = BitmapEx(aBitmap);
    2953             :     }
    2954             : 
    2955          78 :     return !rBitmapEx.IsEmpty();
    2956             : }
    2957             : 
    2958          88 : void GDIMetaFile::UseCanvas( bool _bUseCanvas )
    2959             : {
    2960          88 :     bUseCanvas = _bUseCanvas;
    2961          88 : }
    2962             : 
    2963           0 : MetaCommentAction* makePluggableRendererAction( const OUString& rRendererServiceName,
    2964             :                                                 const OUString& rGraphicServiceName,
    2965             :                                                 const void* _pData,
    2966             :                                                 sal_uInt32 nDataSize )
    2967             : {
    2968           0 :     const sal_uInt8* pData=static_cast<sal_uInt8 const *>(_pData);
    2969             : 
    2970             :     // FIXME: Data gets copied twice, unfortunately
    2971             :     OString aRendererServiceName(
    2972             :         rRendererServiceName.getStr(),
    2973             :         rRendererServiceName.getLength(),
    2974           0 :         RTL_TEXTENCODING_ASCII_US);
    2975             :     OString aGraphicServiceName(
    2976             :         rGraphicServiceName.getStr(),
    2977             :         rGraphicServiceName.getLength(),
    2978           0 :         RTL_TEXTENCODING_ASCII_US);
    2979             : 
    2980             :     std::vector<sal_uInt8> aMem(
    2981           0 :         aRendererServiceName.getLength()+
    2982           0 :         aGraphicServiceName.getLength()+2+nDataSize);
    2983           0 :     sal_uInt8* pMem=&aMem[0];
    2984             : 
    2985             :     std::copy(aRendererServiceName.getStr(),
    2986           0 :               aRendererServiceName.getStr()+aRendererServiceName.getLength()+1,
    2987           0 :               pMem);
    2988           0 :     pMem+=aRendererServiceName.getLength()+1;
    2989             :     std::copy(aGraphicServiceName.getStr(),
    2990           0 :               aGraphicServiceName.getStr()+aGraphicServiceName.getLength()+1,
    2991           0 :               pMem);
    2992           0 :     pMem+=aGraphicServiceName.getLength()+1;
    2993             : 
    2994             :     std::copy(pData,pData+nDataSize,
    2995           0 :               pMem);
    2996             : 
    2997             :     return new MetaCommentAction(
    2998             :         "DELEGATE_PLUGGABLE_RENDERER",
    2999             :         0,
    3000             :         &aMem[0],
    3001           0 :         aMem.size());
    3002             : }
    3003             : 
    3004             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11