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

Generated by: LCOV version 1.10