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

Generated by: LCOV version 1.11