LCOV - code coverage report
Current view: top level - vcl/source/filter/wmf - winmtf.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 851 1184 71.9 %
Date: 2014-11-03 Functions: 69 87 79.3 %
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 "winmtf.hxx"
      21             : #include <basegfx/matrix/b2dhommatrix.hxx>
      22             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      23             : #include <vcl/metaact.hxx>
      24             : #include <vcl/graphictools.hxx>
      25             : #include <vcl/canvastools.hxx>
      26             : #include <vcl/metric.hxx>
      27             : #include <vcl/svapp.hxx>
      28             : #include <rtl/strbuf.hxx>
      29             : #include <rtl/tencinfo.h>
      30             : #include <vcl/virdev.hxx>
      31             : 
      32             : #if OSL_DEBUG_LEVEL > 1
      33             : #define EMFP_DEBUG(x) x
      34             : #else
      35             : #define EMFP_DEBUG(x)
      36             : #endif
      37             : 
      38         624 : void WinMtfClipPath::intersectClipRect( const Rectangle& rRect )
      39             : {
      40             :     maClip.intersectRange(
      41         624 :         vcl::unotools::b2DRectangleFromRectangle(rRect));
      42         624 : }
      43             : 
      44           0 : void WinMtfClipPath::excludeClipRect( const Rectangle& rRect )
      45             : {
      46             :     maClip.subtractRange(
      47           0 :         vcl::unotools::b2DRectangleFromRectangle(rRect));
      48           0 : }
      49             : 
      50         290 : void WinMtfClipPath::setClipPath( const tools::PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode )
      51             : {
      52         290 :     const basegfx::B2DPolyPolygon& rB2DPoly=rPolyPolygon.getB2DPolyPolygon();
      53         290 :     switch ( nClippingMode )
      54             :     {
      55             :         case RGN_OR :
      56           0 :             maClip.unionPolyPolygon(rB2DPoly);
      57           0 :             break;
      58             :         case RGN_XOR :
      59           0 :             maClip.xorPolyPolygon(rB2DPoly);
      60           0 :             break;
      61             :         case RGN_DIFF :
      62           0 :             maClip.subtractPolyPolygon(rB2DPoly);
      63           0 :             break;
      64             :         case RGN_AND :
      65          34 :             maClip.intersectPolyPolygon(rB2DPoly);
      66          34 :             break;
      67             :         case RGN_COPY :
      68         256 :             maClip = basegfx::tools::B2DClipState(rB2DPoly);
      69         256 :             break;
      70         290 :     }
      71         290 : }
      72             : 
      73           0 : void WinMtfClipPath::moveClipRegion( const Size& rSize )
      74             : {
      75             :     // what a weird concept. emulate, don't want this in B2DClipState
      76             :     // API
      77           0 :     basegfx::B2DPolyPolygon aCurrClip=maClip.getClipPoly();
      78           0 :     basegfx::B2DHomMatrix aTranslate;
      79           0 :     aTranslate.translate(rSize.Width(), rSize.Height());
      80             : 
      81           0 :     aCurrClip.transform(aTranslate);
      82           0 :     maClip = basegfx::tools::B2DClipState( aCurrClip );
      83           0 : }
      84             : 
      85         600 : basegfx::B2DPolyPolygon WinMtfClipPath::getClipPath() const
      86             : {
      87         600 :     return maClip.getClipPoly();
      88             : }
      89             : 
      90          92 : void WinMtfPathObj::AddPoint( const Point& rPoint )
      91             : {
      92          92 :     if ( bClosed )
      93          88 :         Insert( Polygon(), POLYPOLY_APPEND );
      94          92 :     Polygon& rPoly = ((tools::PolyPolygon&)*this)[ Count() - 1 ];
      95          92 :     rPoly.Insert( rPoly.GetSize(), rPoint, POLY_NORMAL );
      96          92 :     bClosed = false;
      97          92 : }
      98             : 
      99         108 : void WinMtfPathObj::AddPolyLine( const Polygon& rPolyLine )
     100             : {
     101         108 :     if ( bClosed )
     102           0 :         Insert( Polygon(), POLYPOLY_APPEND );
     103         108 :     Polygon& rPoly = ((tools::PolyPolygon&)*this)[ Count() - 1 ];
     104         108 :     rPoly.Insert( rPoly.GetSize(), rPolyLine );
     105         108 :     bClosed = false;
     106         108 : }
     107             : 
     108           0 : void WinMtfPathObj::AddPolygon( const Polygon& rPoly )
     109             : {
     110           0 :     Insert( rPoly, POLYPOLY_APPEND );
     111           0 :     bClosed = true;
     112           0 : }
     113             : 
     114           0 : void WinMtfPathObj::AddPolyPolygon( const tools::PolyPolygon& rPolyPoly )
     115             : {
     116           0 :     sal_uInt16 i, nCount = rPolyPoly.Count();
     117           0 :     for ( i = 0; i < nCount; i++ )
     118           0 :         Insert( rPolyPoly[ i ], POLYPOLY_APPEND );
     119           0 :     bClosed = true;
     120           0 : }
     121             : 
     122          60 : void WinMtfPathObj::ClosePath()
     123             : {
     124          60 :     if ( Count() )
     125             :     {
     126          60 :         Polygon& rPoly = ((tools::PolyPolygon&)*this)[ Count() - 1 ];
     127          60 :         if ( rPoly.GetSize() > 2 )
     128             :         {
     129          60 :             Point aFirst( rPoly[ 0 ] );
     130          60 :             if ( aFirst != rPoly[ rPoly.GetSize() - 1 ] )
     131          40 :                 rPoly.Insert( rPoly.GetSize(), aFirst, POLY_NORMAL );
     132             :         }
     133             :     }
     134          60 :     bClosed = true;
     135          60 : }
     136             : 
     137        1050 : WinMtfFontStyle::WinMtfFontStyle( LOGFONTW& rFont )
     138             : {
     139             :     rtl_TextEncoding eCharSet;
     140        1050 :     if ( ( rFont.lfCharSet == OEM_CHARSET ) || ( rFont.lfCharSet == DEFAULT_CHARSET ) )
     141          16 :         eCharSet = RTL_TEXTENCODING_MS_1252;
     142             :     else
     143        1034 :         eCharSet = rtl_getTextEncodingFromWindowsCharset( rFont.lfCharSet );
     144        1050 :     if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
     145           0 :         eCharSet = RTL_TEXTENCODING_MS_1252;
     146        1050 :     aFont.SetCharSet( eCharSet );
     147        1050 :     aFont.SetName( rFont.alfFaceName );
     148             :     FontFamily eFamily;
     149        1050 :     switch ( rFont.lfPitchAndFamily & 0xf0 )
     150             :     {
     151             :         case FF_ROMAN:
     152         148 :             eFamily = FAMILY_ROMAN;
     153         148 :         break;
     154             : 
     155             :         case FF_SWISS:
     156         724 :             eFamily = FAMILY_SWISS;
     157         724 :         break;
     158             : 
     159             :         case FF_MODERN:
     160           0 :             eFamily = FAMILY_MODERN;
     161           0 :         break;
     162             : 
     163             :         case FF_SCRIPT:
     164           0 :             eFamily = FAMILY_SCRIPT;
     165           0 :         break;
     166             : 
     167             :         case FF_DECORATIVE:
     168           0 :              eFamily = FAMILY_DECORATIVE;
     169           0 :         break;
     170             : 
     171             :         default:
     172         178 :             eFamily = FAMILY_DONTKNOW;
     173         178 :         break;
     174             :     }
     175        1050 :     aFont.SetFamily( eFamily );
     176             : 
     177             :     FontPitch ePitch;
     178        1050 :     switch ( rFont.lfPitchAndFamily & 0x0f )
     179             :     {
     180             :         case FIXED_PITCH:
     181           0 :             ePitch = PITCH_FIXED;
     182           0 :         break;
     183             : 
     184             :         case DEFAULT_PITCH:
     185             :         case VARIABLE_PITCH:
     186             :         default:
     187        1050 :             ePitch = PITCH_VARIABLE;
     188        1050 :         break;
     189             :     }
     190        1050 :     aFont.SetPitch( ePitch );
     191             : 
     192             :     FontWeight eWeight;
     193        1050 :     if( rFont.lfWeight <= FW_THIN )
     194           0 :         eWeight = WEIGHT_THIN;
     195        1050 :     else if( rFont.lfWeight <= FW_ULTRALIGHT )
     196          14 :         eWeight = WEIGHT_ULTRALIGHT;
     197        1036 :     else if( rFont.lfWeight <= FW_LIGHT )
     198           0 :         eWeight = WEIGHT_LIGHT;
     199        1036 :     else if( rFont.lfWeight <  FW_MEDIUM )
     200         686 :         eWeight = WEIGHT_NORMAL;
     201         350 :     else if( rFont.lfWeight == FW_MEDIUM )
     202           0 :         eWeight = WEIGHT_MEDIUM;
     203         350 :     else if( rFont.lfWeight <= FW_SEMIBOLD )
     204           0 :         eWeight = WEIGHT_SEMIBOLD;
     205         350 :     else if( rFont.lfWeight <= FW_BOLD )
     206         350 :         eWeight = WEIGHT_BOLD;
     207           0 :     else if( rFont.lfWeight <= FW_ULTRABOLD )
     208           0 :         eWeight = WEIGHT_ULTRABOLD;
     209             :     else
     210           0 :         eWeight = WEIGHT_BLACK;
     211        1050 :     aFont.SetWeight( eWeight );
     212             : 
     213        1050 :     if( rFont.lfItalic )
     214         162 :         aFont.SetItalic( ITALIC_NORMAL );
     215             : 
     216        1050 :     if( rFont.lfUnderline )
     217           0 :         aFont.SetUnderline( UNDERLINE_SINGLE );
     218             : 
     219        1050 :     if( rFont.lfStrikeOut )
     220           0 :         aFont.SetStrikeout( STRIKEOUT_SINGLE );
     221             : 
     222        1050 :     if ( rFont.lfOrientation )
     223         238 :         aFont.SetOrientation( (short)rFont.lfOrientation );
     224             :     else
     225         812 :         aFont.SetOrientation( (short)rFont.lfEscapement );
     226             : 
     227        1050 :     Size aFontSize( Size( rFont.lfWidth, rFont.lfHeight ) );
     228        1050 :     if ( rFont.lfHeight > 0 )
     229             :     {
     230             :         // #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
     231          54 :         SolarMutexGuard aGuard;
     232         108 :         VirtualDevice aVDev;
     233             : 
     234             :         // converting the cell height into a font height
     235          54 :         aFont.SetSize( aFontSize );
     236          54 :         aVDev.SetFont( aFont );
     237         108 :         FontMetric aMetric( aVDev.GetFontMetric() );
     238          54 :         long nHeight = aMetric.GetAscent() + aMetric.GetDescent();
     239          54 :         if (nHeight)
     240             :         {
     241          54 :             double fHeight = ((double)aFontSize.Height() * rFont.lfHeight ) / nHeight;
     242          54 :             aFontSize.Height() = (sal_Int32)( fHeight + 0.5 );
     243          54 :         }
     244             :     }
     245             : 
     246             :     // Convert height to positive
     247        1050 :     aFontSize.Height() = std::abs(aFontSize.Height());
     248             : 
     249        1050 :     aFont.SetSize(aFontSize);
     250        1050 : };
     251             : 
     252         419 : WinMtf::WinMtf( WinMtfOutput* pWinMtfOutput, SvStream& rStreamWMF, FilterConfigItem* pConfigItem )
     253             :     : pOut( pWinMtfOutput )
     254             :     , pWMF( &rStreamWMF )
     255             :     , nEndPos( 0 )
     256         419 :     , pFilterConfigItem( pConfigItem )
     257             : {
     258         419 :     SvLockBytes *pLB = pWMF->GetLockBytes();
     259         419 :     if ( pLB )
     260         231 :         pLB->SetSynchronMode( true );
     261             : 
     262         419 :     nStartPos = pWMF->Tell();
     263             : 
     264         419 :     pOut->SetDevOrg( Point() );
     265         419 :     if ( pFilterConfigItem )
     266             :     {
     267           0 :         xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
     268           0 :         if ( xStatusIndicator.is() )
     269             :         {
     270           0 :             OUString aMsg;
     271           0 :             xStatusIndicator->start( aMsg, 100 );
     272             :         }
     273             :     }
     274         419 : }
     275             : 
     276         838 : WinMtf::~WinMtf()
     277             : {
     278         419 :     delete pOut;
     279             : 
     280         419 :     if ( xStatusIndicator.is() )
     281           0 :         xStatusIndicator->end();
     282         419 : }
     283             : 
     284        1996 : void WinMtf::Callback( sal_uInt16 nPercent )
     285             : {
     286        1996 :     if ( xStatusIndicator.is() )
     287           0 :         xStatusIndicator->setValue( nPercent );
     288        1996 : }
     289             : 
     290        6768 : Color WinMtf::ReadColor()
     291             : {
     292             :     sal_uInt32 nColor;
     293        6768 :     pWMF->ReadUInt32( nColor );
     294        6768 :     return Color( (sal_uInt8)nColor, (sal_uInt8)( nColor >> 8 ), (sal_uInt8)( nColor >> 16 ) );
     295             : };
     296             : 
     297           0 : Point WinMtfOutput::ImplScale(const Point& rPoint) // Hack to set varying defaults for incompletely defined files.
     298             : {
     299           0 :     if (!mbIsMapDevSet)
     300           0 :         return Point(rPoint.X() * UNDOCUMENTED_WIN_RCL_RELATION - mrclFrame.Left(),
     301           0 :                      rPoint.Y() * UNDOCUMENTED_WIN_RCL_RELATION - mrclFrame.Top());
     302             :     else
     303           0 :         return rPoint;
     304             : }
     305             : 
     306      124449 : Point WinMtfOutput::ImplMap( const Point& rPt )
     307             : {
     308      124449 :     if ( mnWinExtX && mnWinExtY )
     309             :     {
     310      124449 :         double fX = rPt.X();
     311      124449 :         double fY = rPt.Y();
     312             : 
     313      124449 :         double fX2 = fX * maXForm.eM11 + fY * maXForm.eM21 + maXForm.eDx;
     314      124449 :         double fY2 = fX * maXForm.eM12 + fY * maXForm.eM22 + maXForm.eDy;
     315             : 
     316      124449 :         if ( mnGfxMode == GM_COMPATIBLE )
     317             :         {
     318      123997 :             switch( mnMapMode )
     319             :             {
     320             :                 case MM_LOENGLISH :
     321             :                 {
     322           0 :                     fX2 -= mnWinOrgX;
     323           0 :                     fY2  = mnWinOrgY-fY2;
     324           0 :                     fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
     325           0 :                     fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
     326           0 :                     fX2 += mnDevOrgX;
     327           0 :                     fY2 += mnDevOrgY;
     328             :                 }
     329           0 :                 break;
     330             :                 case MM_HIENGLISH :
     331             :                 {
     332           0 :                     fX2 -= mnWinOrgX;
     333           0 :                     fY2  = mnWinOrgY-fY2;
     334           0 :                     fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
     335           0 :                     fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
     336           0 :                     fX2 += mnDevOrgX;
     337           0 :                     fY2 += mnDevOrgY;
     338             :                 }
     339           0 :                 break;
     340             :                 case MM_TWIPS:
     341             :                 {
     342           0 :                     fX2 -= mnWinOrgX;
     343           0 :                     fY2  = mnWinOrgY-fY2;
     344           0 :                     fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
     345           0 :                     fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
     346           0 :                     fX2 += mnDevOrgX;
     347           0 :                     fY2 += mnDevOrgY;
     348             :                 }
     349           0 :                 break;
     350             :                 case MM_LOMETRIC :
     351             :                 {
     352           0 :                     fX2 -= mnWinOrgX;
     353           0 :                     fY2  = mnWinOrgY-fY2;
     354           0 :                     fX2 *= 10;
     355           0 :                     fY2 *= 10;
     356           0 :                     fX2 += mnDevOrgX;
     357           0 :                     fY2 += mnDevOrgY;
     358             :                 }
     359           0 :                 break;
     360             :                 case MM_HIMETRIC : // in hundredth of a millimeter
     361             :                 {
     362           0 :                     fX2 -= mnWinOrgX;
     363           0 :                     fY2  = mnWinOrgY-fY2;
     364           0 :                     fX2 += mnDevOrgX;
     365           0 :                     fY2 += mnDevOrgY;
     366             :                 }
     367           0 :                 break;
     368             :                 default :
     369             :                 {
     370      123997 :                     fX2 -= mnWinOrgX;
     371      123997 :                     fY2 -= mnWinOrgY;
     372      123997 :                     fX2 /= mnWinExtX;
     373      123997 :                     fY2 /= mnWinExtY;
     374      123997 :                     fX2 *= mnDevWidth;
     375      123997 :                     fY2 *= mnDevHeight;
     376      123997 :                     fX2 += mnDevOrgX;
     377      123997 :                     fY2 += mnDevOrgY;   // fX2, fY2 now in device units
     378      123997 :                     fX2 *= (double)mnMillX * 100.0 / (double)mnPixX;
     379      123997 :                     fY2 *= (double)mnMillY * 100.0 / (double)mnPixY;
     380             :                 }
     381      123997 :                 break;
     382             :             }
     383      123997 :             fX2 -= mrclFrame.Left();
     384      123997 :             fY2 -= mrclFrame.Top();
     385             :         }
     386      124449 :         return Point( FRound( fX2 ), FRound( fY2 ) );
     387             :     }
     388             :     else
     389           0 :         return Point();
     390             : };
     391             : 
     392       21241 : Size WinMtfOutput::ImplMap(const Size& rSz, bool bDoWorldTransform)
     393             : {
     394       21241 :     if ( mnWinExtX && mnWinExtY )
     395             :     {
     396             :         // #i121382# apply the whole WorldTransform, else a rotation will be misinterpreted
     397             :         double fWidth, fHeight;
     398       21241 :         if (bDoWorldTransform)
     399             :         {
     400       20191 :             fWidth = rSz.Width() * maXForm.eM11 + rSz.Height() * maXForm.eM21;
     401       20191 :             fHeight = rSz.Width() * maXForm.eM12 + rSz.Height() * maXForm.eM22;
     402             :         }
     403             :         else
     404             :         {
     405        1050 :             fWidth = rSz.Width();
     406        1050 :             fHeight = rSz.Height();
     407             :         }
     408             : 
     409       21241 :         if ( mnGfxMode == GM_COMPATIBLE )
     410             :         {
     411       21241 :             switch( mnMapMode )
     412             :             {
     413             :                 case MM_LOENGLISH :
     414             :                 {
     415           0 :                     fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
     416           0 :                     fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
     417             :                 }
     418           0 :                 break;
     419             :                 case MM_HIENGLISH :
     420             :                 {
     421           0 :                     fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
     422           0 :                     fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
     423             :                 }
     424           0 :                 break;
     425             :                 case MM_LOMETRIC :
     426             :                 {
     427           0 :                     fWidth *= 10;
     428           0 :                     fHeight*=-10;
     429             :                 }
     430           0 :                 break;
     431             :                 case MM_HIMETRIC : // in hundredth of millimeters
     432             :                 {
     433           0 :                     fHeight *= -1;
     434             :                 }
     435           0 :                 break;
     436             :                 case MM_TWIPS:
     437             :                 {
     438           0 :                     fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
     439           0 :                     fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
     440             :                 }
     441           0 :                 break;
     442             :                 default :
     443             :                 {
     444       21241 :                     fWidth /= mnWinExtX;
     445       21241 :                     fHeight /= mnWinExtY;
     446       21241 :                     fWidth *= mnDevWidth;
     447       21241 :                     fHeight *= mnDevHeight;
     448       21241 :                     fWidth *= (double)mnMillX * 100 / (double)mnPixX;
     449       21241 :                     fHeight *= (double)mnMillY * 100 / (double)mnPixY;
     450             :                 }
     451       21241 :                 break;
     452             :             }
     453             :         }
     454       21241 :         return Size( FRound( fWidth ), FRound( fHeight ) );
     455             :     }
     456             :     else
     457           0 :         return Size();
     458             : }
     459             : 
     460        3280 : Rectangle WinMtfOutput::ImplMap( const Rectangle& rRect )
     461             : {
     462        3280 :     return Rectangle( ImplMap( rRect.TopLeft() ), ImplMap( rRect.GetSize() ) );
     463             : }
     464             : 
     465        1050 : void WinMtfOutput::ImplMap( vcl::Font& rFont )
     466             : {
     467             :     // !!! HACK: we now always set the width to zero because the OS width is interpreted differently;
     468             :     // must later be made portable in SV (KA 1996-02-08)
     469        1050 :     Size  aFontSize = ImplMap (rFont.GetSize(), false);
     470             : 
     471        1050 :     if( aFontSize.Height() < 0 )
     472           2 :         aFontSize.Height() *= -1;
     473             : 
     474        1050 :     rFont.SetSize( aFontSize );
     475             : 
     476        1050 :     if( ( mnWinExtX * mnWinExtY ) < 0 )
     477           0 :         rFont.SetOrientation( 3600 - rFont.GetOrientation() );
     478        1050 : }
     479             : 
     480        3001 : Polygon& WinMtfOutput::ImplMap( Polygon& rPolygon )
     481             : {
     482        3001 :     sal_uInt16 nPoints = rPolygon.GetSize();
     483      114914 :     for ( sal_uInt16 i = 0; i < nPoints; i++ )
     484             :     {
     485      111913 :         rPolygon[ i ] = ImplMap( rPolygon[ i ] );
     486             :     }
     487        3001 :     return rPolygon;
     488             : }
     489             : 
     490           0 : Polygon& WinMtfOutput::ImplScale( Polygon& rPolygon )
     491             : {
     492           0 :     sal_uInt16 nPoints = rPolygon.GetSize();
     493           0 :     for ( sal_uInt16 i = 0; i < nPoints; i++ )
     494             :     {
     495           0 :         rPolygon[ i ] = ImplScale( rPolygon[ i ] );
     496             :     }
     497           0 :     return rPolygon;
     498             : }
     499             : 
     500           0 : tools::PolyPolygon& WinMtfOutput::ImplScale( tools::PolyPolygon& rPolyPolygon )
     501             : {
     502           0 :     sal_uInt16 nPolys = rPolyPolygon.Count();
     503           0 :     for (sal_uInt16 i = 0; i < nPolys; ++i)
     504             :     {
     505           0 :         ImplScale(rPolyPolygon[i]);
     506             :     }
     507           0 :     return rPolyPolygon;
     508             : }
     509             : 
     510         449 : tools::PolyPolygon& WinMtfOutput::ImplMap( tools::PolyPolygon& rPolyPolygon )
     511             : {
     512         449 :     sal_uInt16 nPolys = rPolyPolygon.Count();
     513         449 :     for ( sal_uInt16 i = 0; i < nPolys; ImplMap( rPolyPolygon[ i++ ] ) ) ;
     514         449 :     return rPolyPolygon;
     515             : }
     516             : 
     517       20558 : void WinMtfOutput::SelectObject( sal_Int32 nIndex )
     518             : {
     519       20558 :     GDIObj* pGDIObj = NULL;
     520             : 
     521       20558 :     if ( nIndex & ENHMETA_STOCK_OBJECT )
     522        6810 :         pGDIObj = new GDIObj();
     523             :     else
     524             :     {
     525       13748 :         nIndex &= 0xffff;       // safety check: don't allow index to be > 65535
     526             : 
     527       13748 :         if ( (sal_uInt32)nIndex < vGDIObj.size() )
     528       13748 :             pGDIObj = vGDIObj[ nIndex ];
     529             :     }
     530             : 
     531       20558 :     if( pGDIObj == NULL )
     532       20568 :         return;
     533             : 
     534       20548 :     if ( nIndex & ENHMETA_STOCK_OBJECT )
     535             :     {
     536        6810 :         sal_uInt16 nStockId = (sal_uInt8)nIndex;
     537        6810 :         switch( nStockId )
     538             :         {
     539             :             case WHITE_BRUSH :
     540             :             {
     541         648 :                 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ) ) );
     542             :             }
     543         648 :             break;
     544             :             case LTGRAY_BRUSH :
     545             :             {
     546         390 :                 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_LIGHTGRAY ) ) );
     547             :             }
     548         390 :             break;
     549             :             case GRAY_BRUSH :
     550             :             case DKGRAY_BRUSH :
     551             :             {
     552           6 :                 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_GRAY ) ) );
     553             :             }
     554           6 :             break;
     555             :             case BLACK_BRUSH :
     556             :             {
     557         232 :                 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_BLACK ) ) );
     558             :             }
     559         232 :             break;
     560             :             case NULL_BRUSH :
     561             :             {
     562         162 :                 pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_TRANSPARENT ), true ) );
     563             :             }
     564         162 :             break;
     565             :             case WHITE_PEN :
     566             :             {
     567           0 :                 pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_WHITE ) ) );
     568             :             }
     569           0 :             break;
     570             :             case BLACK_PEN :
     571             :             {
     572        2554 :                 pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_BLACK ) ) );
     573             :             }
     574        2554 :             break;
     575             :             case NULL_PEN :
     576             :             {
     577         268 :                 pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_TRANSPARENT ), true ) );
     578             :             }
     579         268 :             break;
     580             :             default:
     581        2550 :             break;
     582             :         }
     583             :     }
     584       20548 :     if ( pGDIObj->pStyle )
     585             :     {
     586       17998 :         switch( pGDIObj->eType )
     587             :         {
     588             :             case GDI_PEN :
     589        8301 :                 maLineStyle = (WinMtfLineStyle*)pGDIObj->pStyle;
     590        8301 :             break;
     591             :             case GDI_BRUSH :
     592             :             {
     593        5953 :                 maFillStyle = (WinMtfFillStyle*)pGDIObj->pStyle;
     594        5953 :                 mbFillStyleSelected = true;
     595             :             }
     596        5953 :             break;
     597             :             case GDI_FONT :
     598        3744 :                 maFont = ((WinMtfFontStyle*)pGDIObj->pStyle)->aFont;
     599        3744 :             break;
     600             :             default:
     601           0 :             break;  //  -Wall many options not handled.
     602             :         }
     603             :     }
     604       20548 :     if ( nIndex & ENHMETA_STOCK_OBJECT )
     605        6810 :         delete pGDIObj;
     606             : }
     607             : 
     608             : 
     609        3074 : void WinMtfOutput::SetTextLayoutMode( ComplexTextLayoutMode nTextLayoutMode )
     610             : {
     611        3074 :     mnTextLayoutMode = nTextLayoutMode;
     612        3074 : }
     613             : 
     614         779 : void WinMtfOutput::SetBkMode( BkMode nMode )
     615             : {
     616         779 :     mnBkMode = nMode;
     617         779 : }
     618             : 
     619        1260 : void WinMtfOutput::SetBkColor( const Color& rColor )
     620             : {
     621        1260 :     maBkColor = rColor;
     622        1260 : }
     623             : 
     624        1822 : void WinMtfOutput::SetTextColor( const Color& rColor )
     625             : {
     626        1822 :     maTextColor = rColor;
     627        1822 : }
     628             : 
     629         696 : void WinMtfOutput::SetTextAlign( sal_uInt32 nAlign )
     630             : {
     631         696 :     mnTextAlign = nAlign;
     632         696 : }
     633             : 
     634         371 : void WinMtfOutput::ImplResizeObjectArry( sal_uInt32 nNewEntrys )
     635             : {
     636         371 :     vGDIObj.resize(nNewEntrys, NULL);
     637         371 : }
     638             : 
     639           0 : void WinMtfOutput::ImplDrawClippedPolyPolygon( const tools::PolyPolygon& rPolyPoly )
     640             : {
     641           0 :     if ( rPolyPoly.Count() )
     642             :     {
     643           0 :         ImplSetNonPersistentLineColorTransparenz();
     644           0 :         if ( rPolyPoly.Count() == 1 )
     645             :         {
     646           0 :             if ( rPolyPoly.IsRect() )
     647           0 :                 mpGDIMetaFile->AddAction( new MetaRectAction( rPolyPoly.GetBoundRect() ) );
     648             :             else
     649             :             {
     650           0 :                 Polygon aPoly( rPolyPoly[ 0 ] );
     651           0 :                 sal_uInt16 nCount = aPoly.GetSize();
     652           0 :                 if ( nCount )
     653             :                 {
     654           0 :                     if ( aPoly[ nCount - 1 ] != aPoly[ 0 ] )
     655             :                     {
     656           0 :                         Point aPoint( aPoly[ 0 ] );
     657           0 :                         aPoly.Insert( nCount, aPoint );
     658             :                     }
     659           0 :                     mpGDIMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
     660           0 :                 }
     661             :             }
     662             :         }
     663             :         else
     664           0 :             mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) );
     665             :     }
     666           0 : }
     667             : 
     668        1462 : void WinMtfOutput::CreateObject( GDIObjectType eType, void* pStyle )
     669             : {
     670        1462 :     if ( pStyle )
     671             :     {
     672        1462 :         if ( eType == GDI_FONT )
     673             :         {
     674         294 :             WinMtfFontStyle* pFontStyle = (WinMtfFontStyle*) pStyle;
     675         294 :             if (pFontStyle->aFont.GetHeight() == 0)
     676           0 :                 pFontStyle->aFont.SetHeight(423);
     677         294 :             ImplMap(pFontStyle->aFont); // defaulting to 12pt
     678             :         }
     679        1168 :         else if ( eType == GDI_PEN )
     680             :         {
     681         152 :             WinMtfLineStyle* pLineStyle = (WinMtfLineStyle*) pStyle;
     682         152 :             Size aSize(pLineStyle->aLineInfo.GetWidth(), 0);
     683         152 :             aSize = ImplMap(aSize);
     684         152 :             pLineStyle->aLineInfo.SetWidth(aSize.Width());
     685             :         }
     686             :     }
     687             :     sal_uInt32 nIndex;
     688        4064 :     for ( nIndex = 0; nIndex < vGDIObj.size(); nIndex++ )
     689             :     {
     690        3890 :         if ( vGDIObj[ nIndex ] == NULL )
     691        1288 :             break;
     692             :     }
     693        1462 :     if ( nIndex == vGDIObj.size() )
     694         174 :         ImplResizeObjectArry( vGDIObj.size() + 16 );
     695             : 
     696        1462 :     vGDIObj[ nIndex ] = new GDIObj( eType, pStyle );
     697        1462 : }
     698             : 
     699        3168 : void WinMtfOutput::CreateObject( sal_Int32 nIndex, GDIObjectType eType, void* pStyle )
     700             : {
     701        3168 :     if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
     702             :     {
     703        3168 :         nIndex &= 0xffff;       // safety check: do not allow index to be > 65535
     704        3168 :         if ( pStyle )
     705             :         {
     706        3168 :             if ( eType == GDI_FONT )
     707             :             {
     708         756 :                 WinMtfFontStyle* pFontStyle = (WinMtfFontStyle*) pStyle;
     709         756 :                 if (pFontStyle->aFont.GetHeight() == 0)
     710           0 :                     pFontStyle->aFont.SetHeight(423);
     711         756 :                 ImplMap(pFontStyle->aFont);
     712             :             }
     713        2412 :             else if ( eType == GDI_PEN )
     714             :             {
     715        1223 :                 WinMtfLineStyle* pLineStyle = (WinMtfLineStyle*) pStyle;
     716        1223 :                 Size aSize(pLineStyle->aLineInfo.GetWidth(), 0);
     717        1223 :                 aSize = ImplMap(aSize);
     718        1223 :                 pLineStyle->aLineInfo.SetWidth(aSize.Width());
     719             :             }
     720             :         }
     721        3168 :         if ( (sal_uInt32)nIndex >= vGDIObj.size() )
     722         197 :             ImplResizeObjectArry( nIndex + 16 );
     723             : 
     724        3168 :         if ( vGDIObj[ nIndex ] != NULL )
     725           0 :             delete vGDIObj[ nIndex ];
     726             : 
     727        3168 :         vGDIObj[ nIndex ] = new GDIObj( eType, pStyle );
     728             :     }
     729             :     else
     730             :     {
     731           0 :         switch ( eType )
     732             :         {
     733             :             case GDI_PEN :
     734           0 :                 delete (WinMtfLineStyle*)pStyle;
     735           0 :             break;
     736             :             case GDI_BRUSH :
     737           0 :                 delete (WinMtfFillStyle*)pStyle;
     738           0 :             break;
     739             :             case GDI_FONT :
     740           0 :                 delete (WinMtfFontStyle*)pStyle;
     741           0 :             break;
     742             : 
     743             :             default:
     744             :                 OSL_FAIL( "unsupported style not deleted" );
     745           0 :                 break;
     746             :         }
     747             :     }
     748        3168 : }
     749             : 
     750        3936 : void WinMtfOutput::DeleteObject( sal_Int32 nIndex )
     751             : {
     752        3936 :     if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
     753             :     {
     754        3936 :         if ( (sal_uInt32)nIndex < vGDIObj.size() )
     755             :         {
     756        3936 :             delete vGDIObj[ nIndex ];
     757        3936 :             vGDIObj[ nIndex ] = NULL;
     758             :         }
     759             :     }
     760        3936 : }
     761             : 
     762         624 : void WinMtfOutput::IntersectClipRect( const Rectangle& rRect )
     763             : {
     764         624 :     mbClipNeedsUpdate=true;
     765         624 :     if ((rRect.Left()-rRect.Right()==0) && (rRect.Top()-rRect.Bottom()==0))
     766             :     {
     767         624 :         return; // empty rectangles cause trouble
     768             :     }
     769         624 :     aClipPath.intersectClipRect( ImplMap( rRect ) );
     770             : }
     771             : 
     772           0 : void WinMtfOutput::ExcludeClipRect( const Rectangle& rRect )
     773             : {
     774           0 :     mbClipNeedsUpdate=true;
     775           0 :     aClipPath.excludeClipRect( ImplMap( rRect ) );
     776           0 : }
     777             : 
     778           0 : void WinMtfOutput::MoveClipRegion( const Size& rSize )
     779             : {
     780           0 :     mbClipNeedsUpdate=true;
     781           0 :     aClipPath.moveClipRegion( ImplMap( rSize ) );
     782           0 : }
     783             : 
     784         290 : void WinMtfOutput::SetClipPath( const tools::PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode, bool bIsMapped )
     785             : {
     786         290 :     mbClipNeedsUpdate = true;
     787         290 :     tools::PolyPolygon aPolyPolygon(rPolyPolygon);
     788             : 
     789         290 :     if (!bIsMapped)
     790             :     {
     791         254 :         if (!mbIsMapDevSet && (mnMapMode == MM_ISOTROPIC || mnMapMode == MM_ANISOTROPIC))
     792           0 :             aPolyPolygon = ImplScale(aPolyPolygon);
     793             :         else
     794         254 :             aPolyPolygon = ImplMap(aPolyPolygon);
     795             :     }
     796         290 :     aClipPath.setClipPath(aPolyPolygon, nClippingMode);
     797         290 : }
     798             : 
     799         419 : WinMtfOutput::WinMtfOutput( GDIMetaFile& rGDIMetaFile ) :
     800             :     mnLatestTextAlign   ( 0 ),
     801             :     mnTextAlign         ( TA_LEFT | TA_TOP | TA_NOUPDATECP ),
     802             :     maLatestBkColor     ( 0x12345678 ),
     803             :     maBkColor           ( COL_WHITE ),
     804             :     mnLatestTextLayoutMode( TEXT_LAYOUT_DEFAULT ),
     805             :     mnTextLayoutMode    ( TEXT_LAYOUT_DEFAULT ),
     806             :     mnLatestBkMode      ( BkMode::NONE ),
     807             :     mnBkMode            ( BkMode::OPAQUE ),
     808             :     meLatestRasterOp    ( ROP_INVERT ),
     809             :     meRasterOp          ( ROP_OVERPAINT ),
     810             :     maActPos            ( Point() ),
     811             :     mbNopMode           ( false ),
     812             :     mbFillStyleSelected ( false ),
     813             :     mbClipNeedsUpdate   ( true ),
     814             :     mbComplexClip       ( false ),
     815             :     mnGfxMode           ( GM_COMPATIBLE ),
     816             :     mnMapMode           ( MM_TEXT ),
     817             :     mnDevOrgX           ( 0 ),
     818             :     mnDevOrgY           ( 0 ),
     819             :     mnDevWidth          ( 1 ),
     820             :     mnDevHeight         ( 1 ),
     821             :     mnWinOrgX           ( 0 ),
     822             :     mnWinOrgY           ( 0 ),
     823             :     mnWinExtX           ( 1 ),
     824             :     mnWinExtY           ( 1 ),
     825             :     mnPixX              ( 100 ),
     826             :     mnPixY              ( 100 ),
     827             :     mnMillX             ( 1 ),
     828             :     mnMillY             ( 1 ),
     829         419 :     mpGDIMetaFile       ( &rGDIMetaFile )
     830             : {
     831         419 :     mbIsMapWinSet = false;
     832         419 :     mbIsMapDevSet = false;
     833         419 :     mpGDIMetaFile->AddAction( new MetaPushAction( PushFlags::CLIPREGION ) );      // The original clipregion has to be on top
     834             :                                                                             // of the stack so it can always be restored
     835             :                                                                             // this is necessary to be able to support
     836             :                                                                             // SetClipRgn( NULL ) and similar ClipRgn actions (SJ)
     837             : 
     838         419 :     maFont.SetName( "Arial" );                                              // sj: #i57205#, we do have some scaling problems if using
     839         419 :     maFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );                          // the default font then most times a x11 font is used, we
     840         419 :     maFont.SetHeight( 423 );                                                // will prevent this defining a font
     841             : 
     842         419 :     maLatestLineStyle.aLineColor = Color( 0x12, 0x34, 0x56 );
     843         419 :     maLatestFillStyle.aFillColor = Color( 0x12, 0x34, 0x56 );
     844             : 
     845         419 :     mnRop = R2_BLACK + 1;
     846         419 :     SetRasterOp( R2_BLACK );
     847         419 : }
     848             : 
     849        1257 : WinMtfOutput::~WinMtfOutput()
     850             : {
     851         419 :     mpGDIMetaFile->AddAction( new MetaPopAction() );
     852         419 :     mpGDIMetaFile->SetPrefMapMode( MAP_100TH_MM );
     853         419 :     if ( mrclFrame.IsEmpty() )
     854         192 :         mpGDIMetaFile->SetPrefSize( Size( mnDevWidth, mnDevHeight ) );
     855             :     else
     856         227 :         mpGDIMetaFile->SetPrefSize( mrclFrame.GetSize() );
     857             : 
     858        6554 :     for ( sal_uInt32 i = 0; i < vGDIObj.size(); i++ )
     859        6135 :         delete vGDIObj[ i ];
     860         838 : }
     861             : 
     862       13797 : void WinMtfOutput::UpdateClipRegion()
     863             : {
     864       13797 :     if ( mbClipNeedsUpdate )
     865             :     {
     866        1603 :         mbClipNeedsUpdate = false;
     867        1603 :         mbComplexClip = false;
     868             : 
     869        1603 :         mpGDIMetaFile->AddAction( new MetaPopAction() );                    // taking the original clipregion
     870        1603 :         mpGDIMetaFile->AddAction( new MetaPushAction( PushFlags::CLIPREGION ) );
     871             : 
     872             :         // skip for 'no clipping at all' case
     873        1603 :         if( !aClipPath.isEmpty() )
     874             :         {
     875         580 :             const basegfx::B2DPolyPolygon& rClipPoly( aClipPath.getClipPath() );
     876             :             mpGDIMetaFile->AddAction(
     877             :                 new MetaISectRectClipRegionAction(
     878             :                     vcl::unotools::rectangleFromB2DRectangle(
     879         580 :                         rClipPoly.getB2DRange())));
     880             : 
     881         580 :             mbComplexClip = rClipPoly.count() > 1
     882         580 :                 || !basegfx::tools::isRectangle(rClipPoly);
     883             :         }
     884             :     }
     885       13797 : }
     886             : 
     887        2524 : void WinMtfOutput::ImplSetNonPersistentLineColorTransparenz()
     888             : {
     889        2524 :     Color aColor(  COL_TRANSPARENT);
     890        2524 :     WinMtfLineStyle aTransparentLine( aColor, true );
     891        2524 :     if ( ! ( maLatestLineStyle == aTransparentLine ) )
     892             :     {
     893        1602 :         maLatestLineStyle = aTransparentLine;
     894        1602 :         mpGDIMetaFile->AddAction( new MetaLineColorAction( aTransparentLine.aLineColor, !aTransparentLine.bTransparent ) );
     895        2524 :     }
     896        2524 : }
     897             : 
     898        4067 : void WinMtfOutput::UpdateLineStyle()
     899             : {
     900        4067 :     if (!( maLatestLineStyle == maLineStyle ) )
     901             :     {
     902        2181 :         maLatestLineStyle = maLineStyle;
     903        2181 :         mpGDIMetaFile->AddAction( new MetaLineColorAction( maLineStyle.aLineColor, !maLineStyle.bTransparent ) );
     904             :     }
     905        4067 : }
     906             : 
     907        6497 : void WinMtfOutput::UpdateFillStyle()
     908             : {
     909        6497 :     if ( !mbFillStyleSelected )     // SJ: #i57205# taking care of bkcolor if no brush is selected
     910           2 :         maFillStyle = WinMtfFillStyle( maBkColor, mnBkMode == BkMode::TRANSPARENT );
     911        6497 :     if (!( maLatestFillStyle == maFillStyle ) )
     912             :     {
     913        1767 :         maLatestFillStyle = maFillStyle;
     914        1767 :         if (maFillStyle.aType == FillStyleSolid)
     915        1767 :             mpGDIMetaFile->AddAction( new MetaFillColorAction( maFillStyle.aFillColor, !maFillStyle.bTransparent ) );
     916             :     }
     917        6497 : }
     918             : 
     919        7109 : sal_uInt32 WinMtfOutput::SetRasterOp( sal_uInt32 nRasterOp )
     920             : {
     921        7109 :     sal_uInt32 nRetROP = mnRop;
     922        7109 :     if ( nRasterOp != mnRop )
     923             :     {
     924        5647 :         mnRop = nRasterOp;
     925        5647 :         static WinMtfFillStyle aNopFillStyle;
     926        5647 :         static WinMtfLineStyle aNopLineStyle;
     927             : 
     928        5647 :         if ( mbNopMode && ( nRasterOp != R2_NOP ) )
     929             :         {   // changing modes from R2_NOP so set pen and brush
     930           0 :             maFillStyle = aNopFillStyle;
     931           0 :             maLineStyle = aNopLineStyle;
     932           0 :             mbNopMode = false;
     933             :         }
     934        5647 :         switch( nRasterOp )
     935             :         {
     936             :             case R2_NOT:
     937           0 :                 meRasterOp = ROP_INVERT;
     938           0 :             break;
     939             : 
     940             :             case R2_XORPEN:
     941          18 :                 meRasterOp = ROP_XOR;
     942          18 :             break;
     943             : 
     944             :             case R2_NOP:
     945             :             {
     946           0 :                 meRasterOp = ROP_OVERPAINT;
     947           0 :                 if( !mbNopMode )
     948             :                 {
     949           0 :                     aNopFillStyle = maFillStyle;
     950           0 :                     aNopLineStyle = maLineStyle;
     951           0 :                     maFillStyle = WinMtfFillStyle( Color( COL_TRANSPARENT ), true );
     952           0 :                     maLineStyle = WinMtfLineStyle( Color( COL_TRANSPARENT ), true );
     953           0 :                     mbNopMode = true;
     954             :                 }
     955             :             }
     956           0 :             break;
     957             : 
     958             :             default:
     959        5629 :                 meRasterOp = ROP_OVERPAINT;
     960        5629 :             break;
     961             :         }
     962             :     }
     963        7109 :     if ( nRetROP != nRasterOp )
     964        5647 :         mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
     965        7109 :     return nRetROP;
     966             : };
     967             : 
     968          48 : void WinMtfOutput::StrokeAndFillPath( bool bStroke, bool bFill )
     969             : {
     970          48 :     if ( aPathObj.Count() )
     971             :     {
     972          48 :         UpdateClipRegion();
     973          48 :         UpdateLineStyle();
     974          48 :         UpdateFillStyle();
     975          48 :         if ( bFill )
     976             :         {
     977          28 :             if ( !bStroke )
     978             :             {
     979          26 :                 mpGDIMetaFile->AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
     980          26 :                 mpGDIMetaFile->AddAction( new MetaLineColorAction( Color(), false ) );
     981             :             }
     982          28 :             if ( aPathObj.Count() == 1 )
     983          18 :                 mpGDIMetaFile->AddAction( new MetaPolygonAction( aPathObj.GetObject( 0 ) ) );
     984             :             else
     985          10 :                 mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aPathObj ) );
     986             : 
     987          28 :             if ( !bStroke )
     988          26 :                 mpGDIMetaFile->AddAction( new MetaPopAction() );
     989             :         }
     990             :         else
     991             :         {
     992          20 :             sal_uInt16 i, nCount = aPathObj.Count();
     993          40 :             for ( i = 0; i < nCount; i++ )
     994          20 :                 mpGDIMetaFile->AddAction( new MetaPolyLineAction( aPathObj[ i ], maLineStyle.aLineInfo ) );
     995             :         }
     996          48 :         ClearPath();
     997             :     }
     998          48 : }
     999             : 
    1000         108 : void WinMtfOutput::DrawPixel( const Point& rSource, const Color& rColor )
    1001             : {
    1002         108 :     mpGDIMetaFile->AddAction( new MetaPixelAction( ImplMap( rSource), rColor ) );
    1003         108 : }
    1004             : 
    1005        1652 : void WinMtfOutput::MoveTo( const Point& rPoint, bool bRecordPath )
    1006             : {
    1007        1652 :     Point aDest( ImplMap( rPoint ) );
    1008        1652 :     if ( bRecordPath )
    1009             :     {
    1010             :         // fdo#57353 create new subpath for subsequent moves
    1011          92 :         if ( aPathObj.Count() )
    1012          10 :             if ( aPathObj[ aPathObj.Count() - 1 ].GetSize() )
    1013          10 :                 aPathObj.Insert( Polygon(), POLYPOLY_APPEND );
    1014          92 :         aPathObj.AddPoint( aDest );
    1015             :     }
    1016        1652 :     maActPos = aDest;
    1017        1652 : }
    1018             : 
    1019        1506 : void WinMtfOutput::LineTo( const Point& rPoint, bool bRecordPath )
    1020             : {
    1021        1506 :     UpdateClipRegion();
    1022        1506 :     Point aDest( ImplMap( rPoint ) );
    1023        1506 :     if ( bRecordPath )
    1024           0 :         aPathObj.AddPoint( aDest );
    1025             :     else
    1026             :     {
    1027        1506 :         UpdateLineStyle();
    1028        1506 :         mpGDIMetaFile->AddAction( new MetaLineAction( maActPos, aDest, maLineStyle.aLineInfo ) );
    1029             :     }
    1030        1506 :     maActPos = aDest;
    1031        1506 : }
    1032             : 
    1033        2648 : void WinMtfOutput::DrawRect( const Rectangle& rRect, bool bEdge )
    1034             : {
    1035        2648 :     UpdateClipRegion();
    1036        2648 :     UpdateFillStyle();
    1037             : 
    1038        2648 :     if ( mbComplexClip )
    1039             :     {
    1040           0 :         Polygon aPoly( ImplMap( rRect ) );
    1041           0 :         tools::PolyPolygon aPolyPolyRect( aPoly );
    1042           0 :         tools::PolyPolygon aDest;
    1043           0 :         tools::PolyPolygon(aClipPath.getClipPath()).GetIntersection( aPolyPolyRect, aDest );
    1044           0 :         ImplDrawClippedPolyPolygon( aDest );
    1045             :     }
    1046             :     else
    1047             :     {
    1048        2648 :         if ( bEdge )
    1049             :         {
    1050         246 :             if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
    1051             :             {
    1052           8 :                 ImplSetNonPersistentLineColorTransparenz();
    1053           8 :                 mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
    1054           8 :                 UpdateLineStyle();
    1055           8 :                 mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( ImplMap( rRect ) ),maLineStyle.aLineInfo ) );
    1056             :             }
    1057             :             else
    1058             :             {
    1059         238 :                 UpdateLineStyle();
    1060         238 :                 mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
    1061             :             }
    1062             :         }
    1063             :         else
    1064             :         {
    1065        2402 :             ImplSetNonPersistentLineColorTransparenz();
    1066        2402 :             mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
    1067             :         }
    1068             :     }
    1069        2648 : }
    1070             : 
    1071           0 : void WinMtfOutput::DrawRoundRect( const Rectangle& rRect, const Size& rSize )
    1072             : {
    1073           0 :     UpdateClipRegion();
    1074           0 :     UpdateLineStyle();
    1075           0 :     UpdateFillStyle();
    1076           0 :     mpGDIMetaFile->AddAction( new MetaRoundRectAction( ImplMap( rRect ), labs( ImplMap( rSize ).Width() ), labs( ImplMap( rSize ).Height() ) ) );
    1077           0 : }
    1078             : 
    1079           0 : void WinMtfOutput::DrawEllipse( const Rectangle& rRect )
    1080             : {
    1081           0 :     UpdateClipRegion();
    1082           0 :     UpdateFillStyle();
    1083             : 
    1084           0 :     if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
    1085             :     {
    1086           0 :         Point aCenter( ImplMap( rRect.Center() ) );
    1087           0 :         Size  aRad( ImplMap( Size( rRect.GetWidth() / 2, rRect.GetHeight() / 2 ) ) );
    1088             : 
    1089           0 :         ImplSetNonPersistentLineColorTransparenz();
    1090           0 :         mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
    1091           0 :         UpdateLineStyle();
    1092           0 :         mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
    1093             :     }
    1094             :     else
    1095             :     {
    1096           0 :         UpdateLineStyle();
    1097           0 :         mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
    1098             :     }
    1099           0 : }
    1100             : 
    1101           0 : void WinMtfOutput::DrawArc( const Rectangle& rRect, const Point& rStart, const Point& rEnd, bool bTo )
    1102             : {
    1103           0 :     UpdateClipRegion();
    1104           0 :     UpdateLineStyle();
    1105           0 :     UpdateFillStyle();
    1106             : 
    1107           0 :     Rectangle   aRect( ImplMap( rRect ) );
    1108           0 :     Point       aStart( ImplMap( rStart ) );
    1109           0 :     Point       aEnd( ImplMap( rEnd ) );
    1110             : 
    1111           0 :     if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
    1112             :     {
    1113           0 :         if ( aStart == aEnd )
    1114             :         {   // SJ: #i53768# if start & end is identical, then we have to draw a full ellipse
    1115           0 :             Point aCenter( aRect.Center() );
    1116           0 :             Size  aRad( aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
    1117             : 
    1118           0 :             mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
    1119             :         }
    1120             :         else
    1121           0 :             mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_ARC ), maLineStyle.aLineInfo ) );
    1122             :     }
    1123             :     else
    1124           0 :         mpGDIMetaFile->AddAction( new MetaArcAction( aRect, aStart, aEnd ) );
    1125             : 
    1126           0 :     if ( bTo )
    1127           0 :         maActPos = aEnd;
    1128           0 : }
    1129             : 
    1130           0 : void WinMtfOutput::DrawPie( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
    1131             : {
    1132           0 :     UpdateClipRegion();
    1133           0 :     UpdateFillStyle();
    1134             : 
    1135           0 :     Rectangle   aRect( ImplMap( rRect ) );
    1136           0 :     Point       aStart( ImplMap( rStart ) );
    1137           0 :     Point       aEnd( ImplMap( rEnd ) );
    1138             : 
    1139           0 :     if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
    1140             :     {
    1141           0 :         ImplSetNonPersistentLineColorTransparenz();
    1142           0 :         mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
    1143           0 :         UpdateLineStyle();
    1144           0 :         mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_PIE ), maLineStyle.aLineInfo ) );
    1145             :     }
    1146             :     else
    1147             :     {
    1148           0 :         UpdateLineStyle();
    1149           0 :         mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
    1150             :     }
    1151           0 : }
    1152             : 
    1153           0 : void WinMtfOutput::DrawChord( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
    1154             : {
    1155           0 :     UpdateClipRegion();
    1156           0 :     UpdateFillStyle();
    1157             : 
    1158           0 :     Rectangle   aRect( ImplMap( rRect ) );
    1159           0 :     Point       aStart( ImplMap( rStart ) );
    1160           0 :     Point       aEnd( ImplMap( rEnd ) );
    1161             : 
    1162           0 :     if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
    1163             :     {
    1164           0 :         ImplSetNonPersistentLineColorTransparenz();
    1165           0 :         mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
    1166           0 :         UpdateLineStyle();
    1167           0 :         mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_CHORD ), maLineStyle.aLineInfo ) );
    1168             :     }
    1169             :     else
    1170             :     {
    1171           0 :         UpdateLineStyle();
    1172           0 :         mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
    1173             :     }
    1174           0 : }
    1175             : 
    1176        1380 : void WinMtfOutput::DrawPolygon( Polygon& rPolygon, bool bRecordPath )
    1177             : {
    1178        1380 :     UpdateClipRegion();
    1179        1380 :     ImplMap( rPolygon );
    1180        1380 :     if ( bRecordPath )
    1181           0 :         aPathObj.AddPolygon( rPolygon );
    1182             :     else
    1183             :     {
    1184        1380 :         UpdateFillStyle();
    1185             : 
    1186        1380 :         if ( mbComplexClip )
    1187             :         {
    1188           0 :             tools::PolyPolygon aPolyPoly( rPolygon );
    1189           0 :             tools::PolyPolygon aDest;
    1190           0 :             tools::PolyPolygon(aClipPath.getClipPath()).GetIntersection( aPolyPoly, aDest );
    1191           0 :             ImplDrawClippedPolyPolygon( aDest );
    1192             :         }
    1193             :         else
    1194             :         {
    1195        1380 :             if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
    1196             :             {
    1197         114 :                 sal_uInt16 nCount = rPolygon.GetSize();
    1198         114 :                 if ( nCount )
    1199             :                 {
    1200         114 :                     if ( rPolygon[ nCount - 1 ] != rPolygon[ 0 ] )
    1201             :                     {
    1202           0 :                         Point aPoint( rPolygon[ 0 ] );
    1203           0 :                         rPolygon.Insert( nCount, aPoint );
    1204             :                     }
    1205             :                 }
    1206         114 :                 ImplSetNonPersistentLineColorTransparenz();
    1207         114 :                 mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
    1208         114 :                 UpdateLineStyle();
    1209         114 :                 mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
    1210             :             }
    1211             :             else
    1212             :             {
    1213        1266 :                 UpdateLineStyle();
    1214             : 
    1215        1266 :                 if (maLatestFillStyle.aType != FillStylePattern)
    1216        1266 :                     mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
    1217             :                 else {
    1218             :                     SvtGraphicFill aFill = SvtGraphicFill( tools::PolyPolygon( rPolygon ),
    1219             :                                                            Color(),
    1220             :                                                            0.0,
    1221             :                                                            SvtGraphicFill::fillNonZero,
    1222             :                                                            SvtGraphicFill::fillTexture,
    1223             :                                                            SvtGraphicFill::Transform(),
    1224             :                                                            true,
    1225             :                                                            SvtGraphicFill::hatchSingle,
    1226             :                                                            Color(),
    1227             :                                                            SvtGraphicFill::gradientLinear,
    1228             :                                                            Color(),
    1229             :                                                            Color(),
    1230             :                                                            0,
    1231           0 :                                                            Graphic (maLatestFillStyle.aBmp) );
    1232             : 
    1233           0 :                     SvMemoryStream  aMemStm;
    1234             : 
    1235           0 :                     WriteSvtGraphicFill( aMemStm, aFill );
    1236             : 
    1237             :                     mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
    1238             :                                                             static_cast<const sal_uInt8*>(aMemStm.GetData()),
    1239           0 :                                                             aMemStm.Seek( STREAM_SEEK_TO_END ) ) );
    1240           0 :                     mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_END" ) );
    1241             :                 }
    1242             : 
    1243             :             }
    1244             :         }
    1245             :     }
    1246        1380 : }
    1247             : 
    1248         195 : void WinMtfOutput::DrawPolyPolygon( tools::PolyPolygon& rPolyPolygon, bool bRecordPath )
    1249             : {
    1250         195 :     UpdateClipRegion();
    1251             : 
    1252         195 :     ImplMap( rPolyPolygon );
    1253             : 
    1254         195 :     if ( bRecordPath )
    1255           0 :         aPathObj.AddPolyPolygon( rPolyPolygon );
    1256             :     else
    1257             :     {
    1258         195 :         UpdateFillStyle();
    1259             : 
    1260         195 :         if ( mbComplexClip )
    1261             :         {
    1262           0 :             tools::PolyPolygon aDest;
    1263           0 :             tools::PolyPolygon(aClipPath.getClipPath()).GetIntersection( rPolyPolygon, aDest );
    1264           0 :             ImplDrawClippedPolyPolygon( aDest );
    1265             :         }
    1266             :         else
    1267             :         {
    1268         195 :             UpdateLineStyle();
    1269         195 :             mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPolygon ) );
    1270         195 :             if (maLineStyle.aLineInfo.GetWidth() > 0 || maLineStyle.aLineInfo.GetStyle() == LINE_DASH)
    1271             :             {
    1272           8 :                 for (sal_uInt16 nPoly = 0; nPoly < rPolyPolygon.Count(); ++nPoly)
    1273             :                 {
    1274           4 :                     mpGDIMetaFile->AddAction(new MetaPolyLineAction(rPolyPolygon[nPoly], maLineStyle.aLineInfo));
    1275             :                 }
    1276             :             }
    1277             :         }
    1278             :     }
    1279         195 : }
    1280             : 
    1281         718 : void WinMtfOutput::DrawPolyLine( Polygon& rPolygon, bool bTo, bool bRecordPath )
    1282             : {
    1283         718 :     UpdateClipRegion();
    1284             : 
    1285         718 :     ImplMap( rPolygon );
    1286         718 :     if ( bTo )
    1287             :     {
    1288          26 :         rPolygon[ 0 ] = maActPos;
    1289          26 :         maActPos = rPolygon[ rPolygon.GetSize() - 1 ];
    1290             :     }
    1291         718 :     if ( bRecordPath )
    1292          26 :         aPathObj.AddPolyLine( rPolygon );
    1293             :     else
    1294             :     {
    1295         692 :         UpdateLineStyle();
    1296         692 :         mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
    1297             :     }
    1298         718 : }
    1299             : 
    1300          82 : void WinMtfOutput::DrawPolyBezier( Polygon& rPolygon, bool bTo, bool bRecordPath )
    1301             : {
    1302          82 :     UpdateClipRegion();
    1303             : 
    1304          82 :     sal_uInt16 nPoints = rPolygon.GetSize();
    1305          82 :     if ( ( nPoints >= 4 ) && ( ( ( nPoints - 4 ) % 3 ) == 0 ) )
    1306             :     {
    1307          82 :         ImplMap( rPolygon );
    1308          82 :         if ( bTo )
    1309             :         {
    1310          82 :             rPolygon[ 0 ] = maActPos;
    1311          82 :             maActPos = rPolygon[ nPoints - 1 ];
    1312             :         }
    1313             :         sal_uInt16 i;
    1314         638 :         for ( i = 0; ( i + 2 ) < nPoints; )
    1315             :         {
    1316         474 :             rPolygon.SetFlags( i++, POLY_NORMAL );
    1317         474 :             rPolygon.SetFlags( i++, POLY_CONTROL );
    1318         474 :             rPolygon.SetFlags( i++, POLY_CONTROL );
    1319             :         }
    1320          82 :         if ( bRecordPath )
    1321          82 :             aPathObj.AddPolyLine( rPolygon );
    1322             :         else
    1323             :         {
    1324           0 :             UpdateLineStyle();
    1325           0 :             mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
    1326             :         }
    1327             :     }
    1328          82 : }
    1329             : 
    1330        3070 : void WinMtfOutput::DrawText( Point& rPosition, OUString& rText, long* pDXArry, bool bRecordPath, sal_Int32 nGfxMode )
    1331             : {
    1332        3070 :     UpdateClipRegion();
    1333        3070 :     rPosition = ImplMap( rPosition );
    1334        3070 :     sal_Int32 nOldGfxMode = GetGfxMode();
    1335        3070 :     SetGfxMode( GM_COMPATIBLE );
    1336             : 
    1337        3070 :     if (pDXArry)
    1338             :     {
    1339             :         sal_Int32 i;
    1340        2932 :         sal_Int32 nSum = 0;
    1341        2932 :         sal_Int32 nLen = rText.getLength();
    1342             : 
    1343       18932 :         for (i = 0; i < nLen; i++ )
    1344             :         {
    1345       16000 :             if (i > 0)
    1346             :             {
    1347             :                 // #i121382# Map DXArray using WorldTransform
    1348       13068 :                 const Size aSize(ImplMap(Size(nSum, 0)));
    1349       13068 :                 const basegfx::B2DVector aVector(aSize.Width(), aSize.Height());
    1350       13068 :                 pDXArry[i - 1] = basegfx::fround(aVector.getLength());
    1351             :             }
    1352       16000 :             nSum += pDXArry[i];
    1353             :         }
    1354             :     }
    1355        3070 :     if ( mnLatestTextLayoutMode != mnTextLayoutMode )
    1356             :     {
    1357           0 :         mnLatestTextLayoutMode = mnTextLayoutMode;
    1358           0 :         mpGDIMetaFile->AddAction( new MetaLayoutModeAction( mnTextLayoutMode ) );
    1359             :     }
    1360        3070 :     SetGfxMode( nGfxMode );
    1361        3070 :     bool bChangeFont = false;
    1362        3070 :     if ( mnLatestTextAlign != mnTextAlign )
    1363             :     {
    1364         118 :         bChangeFont = true;
    1365         118 :         mnLatestTextAlign = mnTextAlign;
    1366             :         TextAlign eTextAlign;
    1367         118 :         if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
    1368         108 :             eTextAlign = ALIGN_BASELINE;
    1369          10 :         else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
    1370           0 :             eTextAlign = ALIGN_BOTTOM;
    1371             :         else
    1372          10 :             eTextAlign = ALIGN_TOP;
    1373         118 :         mpGDIMetaFile->AddAction( new MetaTextAlignAction( eTextAlign ) );
    1374             :     }
    1375        3070 :     if ( maLatestTextColor != maTextColor )
    1376             :     {
    1377         128 :         bChangeFont = true;
    1378         128 :         maLatestTextColor = maTextColor;
    1379         128 :         mpGDIMetaFile->AddAction( new MetaTextColorAction( maTextColor ) );
    1380             :     }
    1381        3070 :     bool bChangeFillColor = false;
    1382        3070 :     if ( maLatestBkColor != maBkColor )
    1383             :     {
    1384         312 :         bChangeFillColor = true;
    1385         312 :         maLatestBkColor = maBkColor;
    1386             :     }
    1387        3070 :     if ( mnLatestBkMode != mnBkMode )
    1388             :     {
    1389         312 :         bChangeFillColor = true;
    1390         312 :         mnLatestBkMode = mnBkMode;
    1391             :     }
    1392        3070 :     if ( bChangeFillColor )
    1393             :     {
    1394         312 :         bChangeFont = true;
    1395         312 :         mpGDIMetaFile->AddAction( new MetaTextFillColorAction( maFont.GetFillColor(), !maFont.IsTransparent() ) );
    1396             :     }
    1397        3070 :     vcl::Font aTmp( maFont );
    1398        3070 :     aTmp.SetColor( maTextColor );
    1399        3070 :     aTmp.SetFillColor( maBkColor );
    1400             : 
    1401        3070 :     if( mnBkMode == BkMode::TRANSPARENT )
    1402        3070 :         aTmp.SetTransparent( true );
    1403             :     else
    1404           0 :         aTmp.SetTransparent( false );
    1405             : 
    1406        3070 :     if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
    1407         578 :         aTmp.SetAlign( ALIGN_BASELINE );
    1408        2492 :     else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
    1409           0 :         aTmp.SetAlign( ALIGN_BOTTOM );
    1410             :     else
    1411        2492 :         aTmp.SetAlign( ALIGN_TOP );
    1412             : 
    1413        3070 :     if ( nGfxMode == GM_ADVANCED )
    1414             :     {
    1415             :         // check whether there is a font rotation applied via transformation
    1416         226 :         Point aP1( ImplMap( Point() ) );
    1417         226 :         Point aP2( ImplMap( Point( 0, 100 ) ) );
    1418         226 :         aP2.X() -= aP1.X();
    1419         226 :         aP2.Y() -= aP1.Y();
    1420         226 :         double fX = aP2.X();
    1421         226 :         double fY = aP2.Y();
    1422         226 :         if ( fX )
    1423             :         {
    1424          24 :             double fOrientation = acos( fX / sqrt( fX * fX + fY * fY ) ) * 57.29577951308;
    1425          24 :             if ( fY > 0 )
    1426           0 :                 fOrientation = 360 - fOrientation;
    1427          24 :             fOrientation += 90;
    1428          24 :             fOrientation *= 10;
    1429          24 :             fOrientation += aTmp.GetOrientation();
    1430          24 :             aTmp.SetOrientation( sal_Int16( fOrientation ) );
    1431             :         }
    1432             :     }
    1433             : 
    1434        3070 :     if( mnTextAlign & ( TA_UPDATECP | TA_RIGHT_CENTER ) )
    1435             :     {
    1436             :         // #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
    1437          36 :         SolarMutexGuard aGuard;
    1438          72 :         VirtualDevice aVDev;
    1439             : 
    1440             :         sal_Int32 nTextWidth;
    1441          36 :         aVDev.SetMapMode( MapMode( MAP_100TH_MM ) );
    1442          36 :         aVDev.SetFont( maFont );
    1443          36 :         if( pDXArry )
    1444             :         {
    1445          32 :             sal_uInt32 nLen = rText.getLength();
    1446          32 :             nTextWidth = aVDev.GetTextWidth( OUString(rText[ nLen - 1 ]) );
    1447          32 :             if( nLen > 1 )
    1448          32 :                 nTextWidth += pDXArry[ nLen - 2 ];
    1449             :         }
    1450             :         else
    1451           4 :             nTextWidth = aVDev.GetTextWidth( rText );
    1452             : 
    1453          36 :         if( mnTextAlign & TA_UPDATECP )
    1454          28 :             rPosition = maActPos;
    1455             : 
    1456          36 :         if ( mnTextAlign & TA_RIGHT_CENTER )
    1457             :         {
    1458           8 :             double fLength = ( ( mnTextAlign & TA_RIGHT_CENTER ) == TA_RIGHT ) ? nTextWidth : nTextWidth >> 1;
    1459           8 :             rPosition.X() -= (sal_Int32)( fLength * cos( maFont.GetOrientation() * F_PI1800 ) );
    1460           8 :             rPosition.Y() -= (sal_Int32)(-( fLength * sin( maFont.GetOrientation() * F_PI1800 ) ) );
    1461             :         }
    1462             : 
    1463          36 :         if( mnTextAlign & TA_UPDATECP )
    1464          64 :             maActPos.X() = rPosition.X() + nTextWidth;
    1465             :     }
    1466        3070 :     if ( bChangeFont || ( maLatestFont != aTmp ) )
    1467             :     {
    1468         530 :         maLatestFont = aTmp;
    1469         530 :         mpGDIMetaFile->AddAction( new MetaFontAction( aTmp ) );
    1470         530 :         mpGDIMetaFile->AddAction( new MetaTextAlignAction( aTmp.GetAlign() ) );
    1471         530 :         mpGDIMetaFile->AddAction( new MetaTextColorAction( aTmp.GetColor() ) );
    1472         530 :         mpGDIMetaFile->AddAction( new MetaTextFillColorAction( aTmp.GetFillColor(), !aTmp.IsTransparent() ) );
    1473             :     }
    1474        3070 :     if ( bRecordPath )
    1475             :     {
    1476             :         // TODO
    1477             :     }
    1478             :     else
    1479             :     {
    1480             :         /* because text without dx array is badly scaled, we
    1481             :            will create such an array if necessary */
    1482        3070 :         long* pDX = pDXArry;
    1483        3070 :         if (!pDXArry)
    1484             :         {
    1485             :             // #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
    1486         138 :             SolarMutexGuard aGuard;
    1487         276 :             VirtualDevice aVDev;
    1488             : 
    1489         138 :             pDX = new long[ rText.getLength() ];
    1490         138 :             aVDev.SetMapMode( MAP_100TH_MM );
    1491         138 :             aVDev.SetFont( maLatestFont );
    1492         276 :             aVDev.GetTextArray( rText, pDX, 0, rText.getLength());
    1493             :         }
    1494        3070 :         mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, 0, rText.getLength() ) );
    1495        3070 :         if ( !pDXArry )     // this means we have created our own array
    1496         138 :             delete[] pDX;   // which must be deleted
    1497             :     }
    1498        3070 :     SetGfxMode( nOldGfxMode );
    1499        3070 : }
    1500             : 
    1501         268 : void WinMtfOutput::ImplDrawBitmap( const Point& rPos, const Size& rSize, const BitmapEx& rBitmap )
    1502             : {
    1503         268 :     BitmapEx aBmpEx( rBitmap );
    1504         268 :     if ( mbComplexClip )
    1505             :     {
    1506          20 :         VirtualDevice aVDev;
    1507          40 :         MapMode aMapMode( MAP_100TH_MM );
    1508          20 :         aMapMode.SetOrigin( Point( -rPos.X(), -rPos.Y() ) );
    1509          20 :         const Size aOutputSizePixel( aVDev.LogicToPixel( rSize, aMapMode ) );
    1510          20 :         const Size aSizePixel( rBitmap.GetSizePixel() );
    1511          20 :         if ( aOutputSizePixel.Width() && aOutputSizePixel.Height() )
    1512             :         {
    1513          20 :             aMapMode.SetScaleX( Fraction( aSizePixel.Width(), aOutputSizePixel.Width() ) );
    1514          20 :             aMapMode.SetScaleY( Fraction( aSizePixel.Height(), aOutputSizePixel.Height() ) );
    1515             :         }
    1516          20 :         aVDev.SetMapMode( aMapMode );
    1517          20 :         aVDev.SetOutputSizePixel( aSizePixel );
    1518          20 :         aVDev.SetFillColor( Color( COL_BLACK ) );
    1519          40 :         const tools::PolyPolygon aClip( aClipPath.getClipPath() );
    1520          20 :         aVDev.DrawPolyPolygon( aClip );
    1521          20 :         const Point aEmptyPoint;
    1522             : 
    1523             :         // #i50672# Extract whole VDev content (to match size of rBitmap)
    1524          20 :         aVDev.EnableMapMode( false );
    1525          40 :         Bitmap aMask( aVDev.GetBitmap( aEmptyPoint, aSizePixel ).CreateMask( Color( COL_WHITE ) ) );
    1526             : 
    1527          20 :         if ( aBmpEx.IsTransparent() )
    1528             :         {
    1529           0 :             if ( rBitmap.GetTransparentColor() == Color( COL_WHITE ) )
    1530           0 :                 aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_OR );
    1531             :             else
    1532           0 :                 aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_AND );
    1533           0 :             aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask );
    1534             :         }
    1535             :         else
    1536          40 :             aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask );
    1537             :     }
    1538         268 :     if ( aBmpEx.IsTransparent() )
    1539          52 :         mpGDIMetaFile->AddAction( new MetaBmpExScaleAction( rPos, rSize, aBmpEx ) );
    1540             :     else
    1541         216 :         mpGDIMetaFile->AddAction( new MetaBmpScaleAction( rPos, rSize, aBmpEx.GetBitmap() ) );
    1542         268 : }
    1543             : 
    1544        2442 : void WinMtfOutput::ResolveBitmapActions( BSaveStructList_impl& rSaveList )
    1545             : {
    1546        2442 :     UpdateClipRegion();
    1547             : 
    1548        2442 :     size_t nObjects     = rSaveList.size();
    1549        2442 :     size_t nObjectsLeft = nObjects;
    1550             : 
    1551        7352 :     while ( nObjectsLeft )
    1552             :     {
    1553             :         size_t          i;
    1554        2468 :         size_t          nObjectsOfSameSize = 0;
    1555        2468 :         size_t          nObjectStartIndex = nObjects - nObjectsLeft;
    1556             : 
    1557        2468 :         BSaveStruct*    pSave = rSaveList[ nObjectStartIndex ];
    1558        2468 :         Rectangle       aRect( pSave->aOutRect );
    1559             : 
    1560        7400 :         for ( i = nObjectStartIndex; i < nObjects; )
    1561             :         {
    1562        2490 :             nObjectsOfSameSize++;
    1563        2490 :             if ( ++i < nObjects )
    1564             :             {
    1565          48 :                 pSave = rSaveList[ i ];
    1566          48 :                 if ( pSave->aOutRect != aRect )
    1567          26 :                     break;
    1568             :             }
    1569             :         }
    1570        2468 :         Point   aPos( ImplMap( aRect.TopLeft() ) );
    1571        2468 :         Size    aSize( ImplMap( aRect.GetSize() ) );
    1572             : 
    1573        4948 :         for ( i = nObjectStartIndex; i < ( nObjectStartIndex + nObjectsOfSameSize ); i++ )
    1574             :         {
    1575        2480 :             pSave = rSaveList[ i ];
    1576             : 
    1577        2480 :             sal_uInt32  nWinRop = pSave->nWinRop;
    1578        2480 :             sal_uInt8   nRasterOperation = (sal_uInt8)( nWinRop >> 16 );
    1579             : 
    1580        2480 :             sal_uInt32  nUsed =  0;
    1581        2480 :             if ( ( nRasterOperation & 0xf )  != ( nRasterOperation >> 4 ) )
    1582        2226 :                 nUsed |= 1;     // pattern is used
    1583        2480 :             if ( ( nRasterOperation & 0x33 ) != ( ( nRasterOperation & 0xcc ) >> 2 ) )
    1584         254 :                 nUsed |= 2;     // source is used
    1585        2480 :             if ( ( nRasterOperation & 0xaa ) != ( ( nRasterOperation & 0x55 ) << 1 ) )
    1586          36 :                 nUsed |= 4;     // destination is used
    1587             : 
    1588        2480 :             if ( (nUsed & 1) && (( nUsed & 2 ) == 0) && nWinRop != PATINVERT )
    1589             :             {   // patterns aren't well supported yet
    1590        2226 :                 sal_uInt32 nOldRop = SetRasterOp( ROP_OVERPAINT );  // in this case nRasterOperation is either 0 or 0xff
    1591        2226 :                 UpdateFillStyle();
    1592        2226 :                 DrawRect( aRect, false );
    1593        2226 :                 SetRasterOp( nOldRop );
    1594             :             }
    1595             :             else
    1596             :             {
    1597         254 :                 bool bDrawn = false;
    1598             : 
    1599         254 :                 if ( i == nObjectStartIndex )   // optimizing, sometimes it is possible to create just one transparent bitmap
    1600             :                 {
    1601         242 :                     if ( nObjectsOfSameSize == 2 )
    1602             :                     {
    1603          14 :                         BSaveStruct* pSave2 = rSaveList[ i + 1 ];
    1604          28 :                         if ( ( pSave->aBmp.GetPrefSize() == pSave2->aBmp.GetPrefSize() ) &&
    1605          14 :                              ( pSave->aBmp.GetPrefMapMode() == pSave2->aBmp.GetPrefMapMode() ) )
    1606             :                         {
    1607             :                             // TODO: Strictly speaking, we should
    1608             :                             // check whether mask is monochrome, and
    1609             :                             // whether image is black (upper branch)
    1610             :                             // or white (lower branch). Otherwise, the
    1611             :                             // effect is not the same as a masked
    1612             :                             // bitmap.
    1613          14 :                             if ( ( nWinRop == SRCPAINT ) && ( pSave2->nWinRop == SRCAND ) )
    1614             :                             {
    1615           4 :                                 Bitmap aMask( pSave->aBmp ); aMask.Invert();
    1616           8 :                                 BitmapEx aBmpEx( pSave2->aBmp, aMask );
    1617           4 :                                 ImplDrawBitmap( aPos, aSize, aBmpEx );
    1618           4 :                                 bDrawn = true;
    1619           8 :                                 i++;
    1620             :                             }
    1621             :                             // #i20085# This is just the other way
    1622             :                             // around as above. Only difference: mask
    1623             :                             // is inverted
    1624          10 :                             else if ( ( nWinRop == SRCAND ) && ( pSave2->nWinRop == SRCPAINT ) )
    1625             :                             {
    1626           6 :                                 Bitmap aMask( pSave->aBmp );
    1627          12 :                                 BitmapEx aBmpEx( pSave2->aBmp, aMask );
    1628           6 :                                 ImplDrawBitmap( aPos, aSize, aBmpEx );
    1629           6 :                                 bDrawn = true;
    1630          12 :                                 i++;
    1631             :                             }
    1632             :                         }
    1633             :                     }
    1634             :                 }
    1635             : 
    1636         254 :                 if ( !bDrawn )
    1637             :                 {
    1638         244 :                     Push();
    1639         244 :                     sal_uInt32  nOldRop = SetRasterOp( R2_COPYPEN );
    1640         244 :                     Bitmap      aBitmap( pSave->aBmp );
    1641         244 :                     sal_uInt32  nOperation = ( nRasterOperation & 0xf );
    1642         244 :                     switch( nOperation )
    1643             :                     {
    1644             :                         case 0x1 :
    1645             :                         case 0xe :
    1646             :                         {
    1647          14 :                             SetRasterOp( R2_XORPEN );
    1648          14 :                             ImplDrawBitmap( aPos, aSize, aBitmap );
    1649          14 :                             SetRasterOp( R2_COPYPEN );
    1650          14 :                             Bitmap  aMask( aBitmap );
    1651          14 :                             aMask.Invert();
    1652          28 :                             BitmapEx aBmpEx( aBitmap, aMask );
    1653          14 :                             ImplDrawBitmap( aPos, aSize, aBmpEx );
    1654          14 :                             if ( nOperation == 0x1 )
    1655             :                             {
    1656           0 :                                 SetRasterOp( R2_NOT );
    1657           0 :                                 DrawRect( aRect, false );
    1658          14 :                             }
    1659             :                         }
    1660          14 :                         break;
    1661             :                         case 0x7 :
    1662             :                         case 0x8 :
    1663             :                         {
    1664           8 :                             Bitmap  aMask( aBitmap );
    1665           8 :                             if ( ( nUsed & 1 ) && ( nRasterOperation & 0xb0 ) == 0xb0 )     // pattern used
    1666             :                             {
    1667           0 :                                 aBitmap.Convert( BMP_CONVERSION_24BIT );
    1668           0 :                                 aBitmap.Erase( maFillStyle.aFillColor );
    1669             :                             }
    1670          16 :                             BitmapEx aBmpEx( aBitmap, aMask );
    1671           8 :                             ImplDrawBitmap( aPos, aSize, aBmpEx );
    1672           8 :                             if ( nOperation == 0x7 )
    1673             :                             {
    1674           0 :                                 SetRasterOp( R2_NOT );
    1675           0 :                                 DrawRect( aRect, false );
    1676           8 :                             }
    1677             :                         }
    1678           8 :                         break;
    1679             : 
    1680             :                         case 0x4 :
    1681             :                         case 0xb :
    1682             :                         {
    1683           0 :                             SetRasterOp( R2_NOT );
    1684           0 :                             DrawRect( aRect, false );
    1685           0 :                             SetRasterOp( R2_COPYPEN );
    1686           0 :                             Bitmap  aMask( aBitmap );
    1687           0 :                             aBitmap.Invert();
    1688           0 :                             BitmapEx aBmpEx( aBitmap, aMask );
    1689           0 :                             ImplDrawBitmap( aPos, aSize, aBmpEx );
    1690           0 :                             SetRasterOp( R2_XORPEN );
    1691           0 :                             ImplDrawBitmap( aPos, aSize, aBitmap );
    1692           0 :                             if ( nOperation == 0xb )
    1693             :                             {
    1694           0 :                                 SetRasterOp( R2_NOT );
    1695           0 :                                 DrawRect( aRect, false );
    1696           0 :                             }
    1697             :                         }
    1698           0 :                         break;
    1699             : 
    1700             :                         case 0x2 :
    1701             :                         case 0xd :
    1702             :                         {
    1703           0 :                             Bitmap  aMask( aBitmap );
    1704           0 :                             aMask.Invert();
    1705           0 :                             BitmapEx aBmpEx( aBitmap, aMask );
    1706           0 :                             ImplDrawBitmap( aPos, aSize, aBmpEx );
    1707           0 :                             SetRasterOp( R2_XORPEN );
    1708           0 :                             ImplDrawBitmap( aPos, aSize, aBitmap );
    1709           0 :                             if ( nOperation == 0xd )
    1710             :                             {
    1711           0 :                                 SetRasterOp( R2_NOT );
    1712           0 :                                 DrawRect( aRect, false );
    1713           0 :                             }
    1714             :                         }
    1715           0 :                         break;
    1716             :                         case 0x6 :
    1717             :                         case 0x9 :
    1718             :                         {
    1719           4 :                             SetRasterOp( R2_XORPEN );
    1720           4 :                             ImplDrawBitmap( aPos, aSize, aBitmap );
    1721           4 :                             if ( nOperation == 0x9 )
    1722             :                             {
    1723           0 :                                 SetRasterOp( R2_NOT );
    1724           0 :                                 DrawRect( aRect, false );
    1725             :                             }
    1726             :                         }
    1727           4 :                         break;
    1728             : 
    1729             :                         case 0x0 :  // WHITENESS
    1730             :                         case 0xf :  // BLACKNESS
    1731             :                         {                                                   // in this case nRasterOperation is either 0 or 0xff
    1732           0 :                             maFillStyle = WinMtfFillStyle( Color( nRasterOperation, nRasterOperation, nRasterOperation ) );
    1733           0 :                             UpdateFillStyle();
    1734           0 :                             DrawRect( aRect, false );
    1735             :                         }
    1736           0 :                         break;
    1737             : 
    1738             :                         case 0x3 :  // only source is used
    1739             :                         case 0xc :
    1740             :                         {
    1741         218 :                             if ( nRasterOperation == 0x33 )
    1742           0 :                                 aBitmap.Invert();
    1743         218 :                             ImplDrawBitmap( aPos, aSize, aBitmap );
    1744             :                         }
    1745         218 :                         break;
    1746             : 
    1747             :                         case 0x5 :  // only destination is used
    1748             :                         {
    1749           0 :                             SetRasterOp( R2_NOT );
    1750           0 :                             DrawRect( aRect, false );
    1751             :                         }
    1752             :                         case 0xa :  // no operation
    1753           0 :                         break;
    1754             :                     }
    1755         244 :                     SetRasterOp( nOldRop );
    1756         244 :                     Pop();
    1757             :                 }
    1758             :             }
    1759             :         }
    1760        2468 :         nObjectsLeft -= nObjectsOfSameSize;
    1761             :     }
    1762             : 
    1763        4932 :     for( size_t i = 0, n = rSaveList.size(); i < n; ++i )
    1764        2490 :         delete rSaveList[ i ];
    1765        2442 :     rSaveList.clear();
    1766        2442 : }
    1767             : 
    1768         620 : void WinMtfOutput::SetDevOrg( const Point& rPoint )
    1769             : {
    1770         620 :     mnDevOrgX = rPoint.X();
    1771         620 :     mnDevOrgY = rPoint.Y();
    1772         620 : }
    1773             : 
    1774           0 : void WinMtfOutput::SetDevOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
    1775             : {
    1776           0 :     mnDevOrgX += nXAdd;
    1777           0 :     mnDevOrgY += nYAdd;
    1778           0 : }
    1779             : 
    1780         511 : void WinMtfOutput::SetDevExt( const Size& rSize ,bool regular)
    1781             : {
    1782         511 :     if ( rSize.Width() && rSize.Height() )
    1783             :     {
    1784         511 :         switch( mnMapMode )
    1785             :         {
    1786             :             case MM_ISOTROPIC :
    1787             :             case MM_ANISOTROPIC :
    1788             :             {
    1789         511 :                 mnDevWidth = rSize.Width();
    1790         511 :                 mnDevHeight = rSize.Height();
    1791             :             }
    1792             :         }
    1793         511 :         if (regular)
    1794             :         {
    1795         511 :             mbIsMapDevSet=true;
    1796             :         }
    1797             :     }
    1798         511 : }
    1799             : 
    1800           6 : void WinMtfOutput::ScaleDevExt( double fX, double fY )
    1801             : {
    1802           6 :     mnDevWidth = FRound( mnDevWidth * fX );
    1803           6 :     mnDevHeight = FRound( mnDevHeight * fY );
    1804           6 : }
    1805             : 
    1806        1025 : void WinMtfOutput::SetWinOrg( const Point& rPoint , bool bIsEMF)
    1807             : {
    1808        1025 :     mnWinOrgX = rPoint.X();
    1809        1025 :     mnWinOrgY = rPoint.Y();
    1810        1025 :     if (bIsEMF)
    1811             :     {
    1812         353 :         SetDevByWin();
    1813             :     }
    1814        1025 :     mbIsMapWinSet=true;
    1815        1025 : }
    1816             : 
    1817           0 : void WinMtfOutput::SetWinOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
    1818             : {
    1819           0 :     mnWinOrgX += nXAdd;
    1820           0 :     mnWinOrgY += nYAdd;
    1821           0 : }
    1822             : 
    1823         600 : void WinMtfOutput::SetDevByWin() //mnWinExt...-stuff has to be assigned before.
    1824             : {
    1825         600 :     if (!mbIsMapDevSet)
    1826             :     {
    1827         190 :         if ( mnMapMode == MM_ISOTROPIC ) //TODO: WHAT ABOUT ANISOTROPIC???
    1828             :         {
    1829           0 :             Size aSize( (mnWinExtX + mnWinOrgX) >> MS_FIXPOINT_BITCOUNT_28_4,
    1830           0 :                       -((mnWinExtY - mnWinOrgY) >> MS_FIXPOINT_BITCOUNT_28_4));
    1831             : 
    1832           0 :             SetDevExt(aSize, false);
    1833             :         }
    1834             :     }
    1835         600 : }
    1836             : 
    1837         949 : void WinMtfOutput::SetWinExt(const Size& rSize, bool bIsEMF)
    1838             : {
    1839         949 :     if (rSize.Width() && rSize.Height())
    1840             :     {
    1841         929 :         switch( mnMapMode )
    1842             :         {
    1843             :             case MM_ISOTROPIC :
    1844             :             case MM_ANISOTROPIC :
    1845             :             {
    1846         897 :                 mnWinExtX = rSize.Width();
    1847         897 :                 mnWinExtY = rSize.Height();
    1848         897 :                 if (bIsEMF)
    1849             :                 {
    1850         247 :                     SetDevByWin();
    1851             :                 }
    1852         897 :                 mbIsMapWinSet = true;
    1853             :             }
    1854             :         }
    1855             :     }
    1856         949 : }
    1857             : 
    1858           0 : void WinMtfOutput::ScaleWinExt( double fX, double fY )
    1859             : {
    1860           0 :     mnWinExtX = FRound( mnWinExtX * fX );
    1861           0 :     mnWinExtY = FRound( mnWinExtY * fY );
    1862           0 : }
    1863             : 
    1864         223 : void WinMtfOutput::SetrclBounds( const Rectangle& rRect )
    1865             : {
    1866         223 :     mrclBounds = rRect;
    1867         223 : }
    1868             : 
    1869         227 : void WinMtfOutput::SetrclFrame( const Rectangle& rRect )
    1870             : {
    1871         227 :     mrclFrame = rRect;
    1872         227 : }
    1873             : 
    1874         223 : void WinMtfOutput::SetRefPix( const Size& rSize )
    1875             : {
    1876         223 :     mnPixX = rSize.Width();
    1877         223 :     mnPixY = rSize.Height();
    1878         223 : }
    1879             : 
    1880         223 : void WinMtfOutput::SetRefMill( const Size& rSize )
    1881             : {
    1882         223 :     mnMillX = rSize.Width();
    1883         223 :     mnMillY = rSize.Height();
    1884         223 : }
    1885             : 
    1886         445 : void WinMtfOutput::SetMapMode( sal_uInt32 nMapMode )
    1887             : {
    1888         445 :     mnMapMode = nMapMode;
    1889         445 :     if ( nMapMode == MM_TEXT && !mbIsMapWinSet )
    1890             :     {
    1891           0 :         mnWinExtX = mnDevWidth;
    1892           0 :         mnWinExtY = mnDevHeight;
    1893             :     }
    1894         445 :     else if ( mnMapMode == MM_HIMETRIC )
    1895             :     {
    1896           0 :         mnWinExtX = mnMillX * 100;
    1897           0 :         mnWinExtY = mnMillY * 100;
    1898             :     }
    1899         445 : }
    1900             : 
    1901          26 : void WinMtfOutput::SetWorldTransform( const XForm& rXForm )
    1902             : {
    1903          26 :     maXForm.eM11 = rXForm.eM11;
    1904          26 :     maXForm.eM12 = rXForm.eM12;
    1905          26 :     maXForm.eM21 = rXForm.eM21;
    1906          26 :     maXForm.eM22 = rXForm.eM22;
    1907          26 :     maXForm.eDx = rXForm.eDx;
    1908          26 :     maXForm.eDy = rXForm.eDy;
    1909          26 : }
    1910             : 
    1911         128 : void WinMtfOutput::ModifyWorldTransform( const XForm& rXForm, sal_uInt32 nMode )
    1912             : {
    1913         128 :     switch( nMode )
    1914             :     {
    1915             :         case MWT_IDENTITY :
    1916             :         {
    1917           0 :             maXForm.eM11 = maXForm.eM22 = 1.0f;
    1918           0 :             maXForm.eM12 = maXForm.eM21 = maXForm.eDx = maXForm.eDy = 0.0f;
    1919           0 :             break;
    1920             :         }
    1921             : 
    1922             :         case MWT_RIGHTMULTIPLY :
    1923             :         case MWT_LEFTMULTIPLY :
    1924             :         {
    1925             :             const XForm* pLeft;
    1926             :             const XForm* pRight;
    1927             : 
    1928         128 :             if ( nMode == MWT_LEFTMULTIPLY )
    1929             :             {
    1930         128 :                 pLeft = &rXForm;
    1931         128 :                 pRight = &maXForm;
    1932             :             }
    1933             :             else
    1934             :             {
    1935           0 :                 pLeft = &maXForm;
    1936           0 :                 pRight = &rXForm;
    1937             :             }
    1938             : 
    1939             :             float aF[3][3];
    1940             :             float bF[3][3];
    1941             :             float cF[3][3];
    1942             : 
    1943         128 :             aF[0][0] = pLeft->eM11;
    1944         128 :             aF[0][1] = pLeft->eM12;
    1945         128 :             aF[0][2] = 0;
    1946         128 :             aF[1][0] = pLeft->eM21;
    1947         128 :             aF[1][1] = pLeft->eM22;
    1948         128 :             aF[1][2] = 0;
    1949         128 :             aF[2][0] = pLeft->eDx;
    1950         128 :             aF[2][1] = pLeft->eDy;
    1951         128 :             aF[2][2] = 1;
    1952             : 
    1953         128 :             bF[0][0] = pRight->eM11;
    1954         128 :             bF[0][1] = pRight->eM12;
    1955         128 :             bF[0][2] = 0;
    1956         128 :             bF[1][0] = pRight->eM21;
    1957         128 :             bF[1][1] = pRight->eM22;
    1958         128 :             bF[1][2] = 0;
    1959         128 :             bF[2][0] = pRight->eDx;
    1960         128 :             bF[2][1] = pRight->eDy;
    1961         128 :             bF[2][2] = 1;
    1962             : 
    1963             :             int i, j, k;
    1964         512 :             for ( i = 0; i < 3; i++ )
    1965             :             {
    1966        1536 :               for ( j = 0; j < 3; j++ )
    1967             :               {
    1968        1152 :                  cF[i][j] = 0;
    1969        4608 :                  for ( k = 0; k < 3; k++ )
    1970        3456 :                     cF[i][j] += aF[i][k] * bF[k][j];
    1971             :               }
    1972             :             }
    1973         128 :             maXForm.eM11 = cF[0][0];
    1974         128 :             maXForm.eM12 = cF[0][1];
    1975         128 :             maXForm.eM21 = cF[1][0];
    1976         128 :             maXForm.eM22 = cF[1][1];
    1977         128 :             maXForm.eDx = cF[2][0];
    1978         128 :             maXForm.eDy = cF[2][1];
    1979         128 :             break;
    1980             :         }
    1981             :         case MWT_SET:
    1982             :         {
    1983           0 :             SetWorldTransform(rXForm);
    1984           0 :             break;
    1985             :         }
    1986             :     }
    1987         128 : }
    1988             : 
    1989        1708 : void WinMtfOutput::Push()                       // !! to be able to access the original ClipRegion it
    1990             : {                                               // is not allowed to use the MetaPushAction()
    1991        1708 :     UpdateClipRegion();                         // (the original clip region is on top of the stack) (SJ)
    1992        1708 :     SaveStructPtr pSave( new SaveStruct );
    1993             : 
    1994        1708 :     pSave->aLineStyle = maLineStyle;
    1995        1708 :     pSave->aFillStyle = maFillStyle;
    1996             : 
    1997        1708 :     pSave->aFont = maFont;
    1998        1708 :     pSave->aTextColor = maTextColor;
    1999        1708 :     pSave->nTextAlign = mnTextAlign;
    2000        1708 :     pSave->nTextLayoutMode = mnTextLayoutMode;
    2001        1708 :     pSave->nMapMode = mnMapMode;
    2002        1708 :     pSave->nGfxMode = mnGfxMode;
    2003        1708 :     pSave->nBkMode = mnBkMode;
    2004        1708 :     pSave->aBkColor = maBkColor;
    2005        1708 :     pSave->bFillStyleSelected = mbFillStyleSelected;
    2006             : 
    2007        1708 :     pSave->aActPos = maActPos;
    2008        1708 :     pSave->aXForm = maXForm;
    2009        1708 :     pSave->eRasterOp = meRasterOp;
    2010             : 
    2011        1708 :     pSave->nWinOrgX = mnWinOrgX;
    2012        1708 :     pSave->nWinOrgY = mnWinOrgY;
    2013        1708 :     pSave->nWinExtX = mnWinExtX;
    2014        1708 :     pSave->nWinExtY = mnWinExtY;
    2015        1708 :     pSave->nDevOrgX = mnDevOrgX;
    2016        1708 :     pSave->nDevOrgY = mnDevOrgY;
    2017        1708 :     pSave->nDevWidth = mnDevWidth;
    2018        1708 :     pSave->nDevHeight = mnDevHeight;
    2019             : 
    2020        1708 :     pSave->aPathObj = aPathObj;
    2021        1708 :     pSave->aClipPath = aClipPath;
    2022             : 
    2023        1708 :     vSaveStack.push_back( pSave );
    2024        1708 : }
    2025             : 
    2026        1622 : void WinMtfOutput::Pop()
    2027             : {
    2028             :     // Get the latest data from the stack
    2029        1622 :     if( !vSaveStack.empty() )
    2030             :     {
    2031             :         // Backup the current data on the stack
    2032        1622 :         SaveStructPtr pSave( vSaveStack.back() );
    2033             : 
    2034        1622 :         maLineStyle = pSave->aLineStyle;
    2035        1622 :         maFillStyle = pSave->aFillStyle;
    2036             : 
    2037        1622 :         maFont = pSave->aFont;
    2038        1622 :         maTextColor = pSave->aTextColor;
    2039        1622 :         mnTextAlign = pSave->nTextAlign;
    2040        1622 :         mnTextLayoutMode = pSave->nTextLayoutMode;
    2041        1622 :         mnBkMode = pSave->nBkMode;
    2042        1622 :         mnGfxMode = pSave->nGfxMode;
    2043        1622 :         mnMapMode = pSave->nMapMode;
    2044        1622 :         maBkColor = pSave->aBkColor;
    2045        1622 :         mbFillStyleSelected = pSave->bFillStyleSelected;
    2046             : 
    2047        1622 :         maActPos = pSave->aActPos;
    2048        1622 :         maXForm = pSave->aXForm;
    2049        1622 :         meRasterOp = pSave->eRasterOp;
    2050             : 
    2051        1622 :         mnWinOrgX = pSave->nWinOrgX;
    2052        1622 :         mnWinOrgY = pSave->nWinOrgY;
    2053        1622 :         mnWinExtX = pSave->nWinExtX;
    2054        1622 :         mnWinExtY = pSave->nWinExtY;
    2055        1622 :         mnDevOrgX = pSave->nDevOrgX;
    2056        1622 :         mnDevOrgY = pSave->nDevOrgY;
    2057        1622 :         mnDevWidth = pSave->nDevWidth;
    2058        1622 :         mnDevHeight = pSave->nDevHeight;
    2059             : 
    2060        1622 :         aPathObj = pSave->aPathObj;
    2061        1622 :         if ( ! ( aClipPath == pSave->aClipPath ) )
    2062             :         {
    2063         746 :             aClipPath = pSave->aClipPath;
    2064         746 :             mbClipNeedsUpdate = true;
    2065             :         }
    2066        1622 :         if ( meLatestRasterOp != meRasterOp )
    2067        1622 :             mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
    2068        1622 :         vSaveStack.pop_back();
    2069             :     }
    2070        1622 : }
    2071             : 
    2072           4 : void WinMtfOutput::AddFromGDIMetaFile( GDIMetaFile& rGDIMetaFile )
    2073             : {
    2074           4 :    rGDIMetaFile.Play( *mpGDIMetaFile, 0xFFFFFFFF );
    2075           4 : }
    2076             : 
    2077         124 : void WinMtfOutput::PassEMFPlusHeaderInfo()
    2078             : {
    2079             :     EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS header info\n"));
    2080             : 
    2081         124 :     SvMemoryStream mem;
    2082             :     sal_Int32 nLeft, nRight, nTop, nBottom;
    2083             : 
    2084         124 :     nLeft = mrclFrame.Left();
    2085         124 :     nTop = mrclFrame.Top();
    2086         124 :     nRight = mrclFrame.Right();
    2087         124 :     nBottom = mrclFrame.Bottom();
    2088             : 
    2089             :     // emf header info
    2090         124 :     mem.WriteInt32( nLeft ).WriteInt32( nTop ).WriteInt32( nRight ).WriteInt32( nBottom );
    2091         124 :     mem.WriteInt32( mnPixX ).WriteInt32( mnPixY ).WriteInt32( mnMillX ).WriteInt32( mnMillY );
    2092             : 
    2093             :     float one, zero;
    2094             : 
    2095         124 :     one = 1;
    2096         124 :     zero = 0;
    2097             : 
    2098             :     // add transformation matrix to be used in vcl's metaact.cxx for
    2099             :     // rotate and scale operations
    2100         124 :     mem.WriteFloat( one ).WriteFloat( zero ).WriteFloat( zero ).WriteFloat( one ).WriteFloat( zero ).WriteFloat( zero );
    2101             : 
    2102             :     // need to flush the stream, otherwise GetEndOfData will return 0
    2103             :     // on windows where the function parameters are probably resolved in reverse order
    2104         124 :     mem.Flush();
    2105             : 
    2106         124 :     mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS_HEADER_INFO", 0, (const sal_uInt8*) mem.GetData(), mem.GetEndOfData() ) );
    2107         124 :     mpGDIMetaFile->UseCanvas( true );
    2108         124 : }
    2109             : 
    2110         908 : void WinMtfOutput::PassEMFPlus( void* pBuffer, sal_uInt32 nLength )
    2111             : {
    2112             :     EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS comment length %04x\n",(unsigned int) nLength));
    2113         908 :     mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS", 0, static_cast<const sal_uInt8*>(pBuffer), nLength ) );
    2114        2141 : }
    2115             : 
    2116             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10