LCOV - code coverage report
Current view: top level - vcl/source/filter/wmf - wmfwr.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 685 1066 64.3 %
Date: 2014-11-03 Functions: 53 64 82.8 %
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 "sal/config.h"
      21             : 
      22             : #include <algorithm>
      23             : 
      24             : #include "wmfwr.hxx"
      25             : #include <unotools/fontcvt.hxx>
      26             : #include "emfwr.hxx"
      27             : #include <rtl/crc.h>
      28             : #include <rtl/tencinfo.h>
      29             : #include <tools/bigint.hxx>
      30             : #include <tools/helpers.hxx>
      31             : #include <tools/tenccvt.hxx>
      32             : #include <osl/endian.h>
      33             : #include <vcl/dibtools.hxx>
      34             : #include <vcl/metric.hxx>
      35             : #include <basegfx/polygon/b2dpolygon.hxx>
      36             : #include <basegfx/polygon/b2dpolypolygon.hxx>
      37             : #include <boost/scoped_array.hpp>
      38             : 
      39             : // MS Windows defines
      40             : 
      41             : #define W_META_SETBKMODE            0x0102
      42             : #define W_META_SETROP2              0x0104
      43             : #define W_META_SETSTRETCHBLTMODE    0x0107
      44             : #define W_META_SETTEXTCOLOR         0x0209
      45             : #define W_META_SETWINDOWORG         0x020B
      46             : #define W_META_SETWINDOWEXT         0x020C
      47             : #define W_META_LINETO               0x0213
      48             : #define W_META_MOVETO               0x0214
      49             : #define W_META_INTERSECTCLIPRECT    0x0416
      50             : #define W_META_ARC                  0x0817
      51             : #define W_META_ELLIPSE              0x0418
      52             : #define W_META_PIE                  0x081A
      53             : #define W_META_RECTANGLE            0x041B
      54             : #define W_META_ROUNDRECT            0x061C
      55             : #define W_META_SAVEDC               0x001E
      56             : #define W_META_SETPIXEL             0x041F
      57             : #define W_META_TEXTOUT              0x0521
      58             : #define W_META_POLYGON              0x0324
      59             : #define W_META_POLYLINE             0x0325
      60             : #define W_META_ESCAPE               0x0626
      61             : #define W_META_RESTOREDC            0x0127
      62             : #define W_META_SELECTOBJECT         0x012D
      63             : #define W_META_SETTEXTALIGN         0x012E
      64             : #define W_META_CHORD                0x0830
      65             : #define W_META_EXTTEXTOUT           0x0a32
      66             : #define W_META_POLYPOLYGON          0x0538
      67             : #define W_META_STRETCHDIB           0x0f43
      68             : #define W_META_DELETEOBJECT         0x01f0
      69             : #define W_META_CREATEPENINDIRECT    0x02FA
      70             : #define W_META_CREATEFONTINDIRECT   0x02FB
      71             : #define W_META_CREATEBRUSHINDIRECT  0x02FC
      72             : 
      73             : #define W_TRANSPARENT     1
      74             : #define W_OPAQUE          2
      75             : 
      76             : #define W_R2_NOT              6
      77             : #define W_R2_XORPEN           7
      78             : #define W_R2_COPYPEN          13
      79             : 
      80             : #define W_TA_NOUPDATECP      0x0000
      81             : #define W_TA_LEFT            0x0000
      82             : #define W_TA_RIGHT           0x0002
      83             : #define W_TA_TOP             0x0000
      84             : #define W_TA_BOTTOM          0x0008
      85             : #define W_TA_BASELINE        0x0018
      86             : #define W_TA_RTLREADING      0x0100
      87             : 
      88             : #define W_SRCCOPY             0x00CC0020L
      89             : #define W_SRCPAINT            0x00EE0086L
      90             : #define W_SRCAND              0x008800C6L
      91             : #define W_SRCINVERT           0x00660046L
      92             : #define W_DSTINVERT           0x00550009L
      93             : 
      94             : #define W_PS_SOLID            0
      95             : #define W_PS_DASH             1
      96             : #define W_PS_DOT              2
      97             : #define W_PS_DASHDOT          3
      98             : #define W_PS_DASHDOTDOT       4
      99             : #define W_PS_NULL             5
     100             : 
     101             : #define W_LF_FACESIZE       32
     102             : 
     103             : #define W_ANSI_CHARSET          0
     104             : 
     105             : #define W_DEFAULT_PITCH       0x00
     106             : #define W_FIXED_PITCH         0x01
     107             : #define W_VARIABLE_PITCH      0x02
     108             : 
     109             : #define W_FF_DONTCARE         0x00
     110             : #define W_FF_ROMAN            0x10
     111             : #define W_FF_SWISS            0x20
     112             : #define W_FF_MODERN           0x30
     113             : #define W_FF_SCRIPT           0x40
     114             : #define W_FF_DECORATIVE       0x50
     115             : 
     116             : #define W_FW_DONTCARE       0
     117             : #define W_FW_THIN           100
     118             : #define W_FW_LIGHT          300
     119             : #define W_FW_NORMAL         400
     120             : #define W_FW_MEDIUM         500
     121             : #define W_FW_SEMIBOLD       600
     122             : #define W_FW_BOLD           700
     123             : #define W_FW_ULTRALIGHT     200
     124             : #define W_FW_ULTRABOLD      800
     125             : #define W_FW_BLACK          900
     126             : 
     127             : #define W_BS_SOLID          0
     128             : #define W_BS_HOLLOW         1
     129             : 
     130             : #define W_MFCOMMENT         15
     131             : 
     132             : #define PRIVATE_ESCAPE_UNICODE          2
     133             : 
     134          70 : WMFWriter::WMFWriter()
     135             :     : bStatus(false)
     136             :     , nLastPercent(0)
     137             :     , pWMF(NULL)
     138             :     , pVirDev(NULL)
     139             :     , nMetafileHeaderPos(0)
     140             :     , nMaxRecordSize(0)
     141             :     , nActRecordPos(0)
     142             :     , eSrcRasterOp(ROP_OVERPAINT)
     143             :     , eSrcTextAlign(ALIGN_BASELINE)
     144             :     , bSrcIsClipping(false)
     145             :     , pAttrStack(NULL)
     146             :     , eSrcHorTextAlign(W_TA_LEFT)
     147             :     , eDstROP2(ROP_OVERPAINT)
     148             :     , eDstTextAlign(ALIGN_BASELINE)
     149             :     , eDstHorTextAlign(W_TA_LEFT)
     150             :     , bDstIsClipping(false)
     151             :     , nDstPenHandle(0)
     152             :     , nDstFontHandle(0)
     153             :     , nDstBrushHandle(0)
     154             :     , nNumberOfActions(0)
     155             :     , nNumberOfBitmaps(0)
     156             :     , nWrittenActions(0)
     157             :     , nWrittenBitmaps(0)
     158             :     , nActBitmapPercent(0)
     159          70 :     , bEmbedEMF(false)
     160             : {
     161          70 : }
     162             : 
     163        5736 : void WMFWriter::MayCallback()
     164             : {
     165        5736 :     if ( xStatusIndicator.is() )
     166             :     {
     167             :         sal_uLong nPercent;
     168             : 
     169             :         // we simply assume that 16386 actions match to a bitmap
     170             :         // (normally a metafile either contains only actions or some bitmaps and
     171             :         // almost no actions. In which case the ratio is less important)
     172             : 
     173           0 :         nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
     174           0 :                 *100
     175           0 :                 /((nNumberOfBitmaps<<14)+nNumberOfActions);
     176             : 
     177           0 :         if ( nPercent >= nLastPercent + 3 )
     178             :         {
     179           0 :             nLastPercent = nPercent;
     180           0 :             if( nPercent <= 100 )
     181           0 :                 xStatusIndicator->setValue( nPercent );
     182             :         }
     183             :     }
     184        5736 : }
     185             : 
     186          70 : void WMFWriter::CountActionsAndBitmaps( const GDIMetaFile & rMTF )
     187             : {
     188             :     size_t nAction, nActionCount;
     189             : 
     190          70 :     nActionCount = rMTF.GetActionSize();
     191             : 
     192        5790 :     for ( nAction=0; nAction < nActionCount; nAction++ )
     193             :     {
     194        5720 :         MetaAction* pMA = rMTF.GetAction( nAction );
     195             : 
     196        5720 :         switch( pMA->GetType() )
     197             :         {
     198             :             case META_BMP_ACTION:
     199             :             case META_BMPSCALE_ACTION:
     200             :             case META_BMPSCALEPART_ACTION:
     201             :             case META_BMPEX_ACTION:
     202             :             case META_BMPEXSCALE_ACTION:
     203             :             case META_BMPEXSCALEPART_ACTION:
     204          10 :                 nNumberOfBitmaps++;
     205          10 :             break;
     206             :         }
     207        5720 :         nNumberOfActions++;
     208             :     }
     209          70 : }
     210             : 
     211        7408 : void WMFWriter::WritePointXY(const Point & rPoint)
     212             : {
     213        7408 :     Point aPt( OutputDevice::LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
     214        7408 :     pWMF->WriteInt16( aPt.X() ).WriteInt16( aPt.Y() );
     215        7408 : }
     216             : 
     217         744 : void WMFWriter::WritePointYX(const Point & rPoint)
     218             : {
     219         744 :     Point aPt( OutputDevice::LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
     220         744 :     pWMF->WriteInt16( aPt.Y() ).WriteInt16( aPt.X() );
     221         744 : }
     222             : 
     223         138 : sal_Int32 WMFWriter::ScaleWidth( sal_Int32 nDX )
     224             : {
     225         138 :     Size aSz( OutputDevice::LogicToLogic(Size(nDX,0),aSrcMapMode,aTargetMapMode) );
     226         138 :     return aSz.Width();
     227             : }
     228             : 
     229         356 : void WMFWriter::WriteSize(const Size & rSize)
     230             : {
     231         356 :     Size aSz( OutputDevice::LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
     232         356 :     pWMF->WriteInt16( aSz.Width() ).WriteInt16( aSz.Height() );
     233         356 : }
     234             : 
     235         908 : void WMFWriter::WriteHeightWidth(const Size & rSize)
     236             : {
     237         908 :     Size aSz( OutputDevice::LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
     238         908 :     pWMF->WriteInt16( aSz.Height() ).WriteInt16( aSz.Width() );
     239         908 : }
     240             : 
     241         108 : void WMFWriter::WriteRectangle(const Rectangle & rRect)
     242             : {
     243         108 :     WritePointYX(Point(rRect.Right()+1,rRect.Bottom()+1));
     244         108 :     WritePointYX(rRect.TopLeft());
     245         108 : }
     246             : 
     247        1468 : void WMFWriter::WriteColor(const Color & rColor)
     248             : {
     249        1468 :     pWMF->WriteUChar(  rColor.GetRed() ).WriteUChar( rColor.GetGreen() ).WriteUChar( rColor.GetBlue() ).WriteUChar( 0 );
     250        1468 : }
     251             : 
     252        8946 : void WMFWriter::WriteRecordHeader(sal_uInt32 nSizeWords, sal_uInt16 nType)
     253             : {
     254        8946 :     nActRecordPos=pWMF->Tell();
     255        8946 :     if (nSizeWords>nMaxRecordSize) nMaxRecordSize=nSizeWords;
     256        8946 :     pWMF->WriteUInt32( nSizeWords ).WriteUInt16( nType );
     257        8946 : }
     258             : 
     259        2182 : void WMFWriter::UpdateRecordHeader()
     260             : {
     261             :     sal_uLong nPos;
     262             :     sal_uInt32 nSize;
     263             : 
     264        2182 :     nPos=pWMF->Tell(); nSize=nPos-nActRecordPos;
     265        2182 :     if ((nSize & 1)!=0) {
     266           0 :         pWMF->WriteUChar( 0 );
     267           0 :         nPos++; nSize++;
     268             :     }
     269        2182 :     nSize/=2;
     270        2182 :     if (nSize>nMaxRecordSize) nMaxRecordSize=nSize;
     271        2182 :     pWMF->Seek(nActRecordPos);
     272        2182 :     pWMF->WriteUInt32( nSize );
     273        2182 :     pWMF->Seek(nPos);
     274        2182 : }
     275             : 
     276           0 : void WMFWriter::WMFRecord_Arc(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
     277             : {
     278           0 :     WriteRecordHeader(0x0000000b,W_META_ARC);
     279           0 :     WritePointYX(rEndPt);
     280           0 :     WritePointYX(rStartPt);
     281           0 :     WriteRectangle(rRect);
     282           0 : }
     283             : 
     284           0 : void WMFWriter::WMFRecord_Chord(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
     285             : {
     286           0 :     WriteRecordHeader(0x0000000b,W_META_CHORD);
     287           0 :     WritePointYX(rEndPt);
     288           0 :     WritePointYX(rStartPt);
     289           0 :     WriteRectangle(rRect);
     290           0 : }
     291             : 
     292         356 : void WMFWriter::WMFRecord_CreateBrushIndirect(const Color& rColor)
     293             : {
     294         356 :     WriteRecordHeader(0x00000007,W_META_CREATEBRUSHINDIRECT);
     295             : 
     296         356 :     if( rColor==Color(COL_TRANSPARENT) )
     297           4 :         pWMF->WriteUInt16( W_BS_HOLLOW );
     298             :     else
     299         352 :         pWMF->WriteUInt16( W_BS_SOLID );
     300             : 
     301         356 :     WriteColor( rColor );
     302         356 :     pWMF->WriteUInt16( 0 );
     303         356 : }
     304             : 
     305         822 : void WMFWriter::WMFRecord_CreateFontIndirect(const vcl::Font & rFont)
     306             : {
     307             :     sal_uInt16 nWeight,i;
     308             :     sal_uInt8 nPitchFamily;
     309             : 
     310         822 :     WriteRecordHeader(0x00000000,W_META_CREATEFONTINDIRECT);
     311         822 :     WriteHeightWidth(Size(rFont.GetSize().Width(),-rFont.GetSize().Height()));
     312         822 :     pWMF->WriteInt16( rFont.GetOrientation() ).WriteInt16( rFont.GetOrientation() );
     313             : 
     314         822 :     switch (rFont.GetWeight()) {
     315           0 :         case WEIGHT_THIN:       nWeight=W_FW_THIN;       break;
     316           0 :         case WEIGHT_ULTRALIGHT: nWeight=W_FW_ULTRALIGHT; break;
     317           0 :         case WEIGHT_LIGHT:      nWeight=W_FW_LIGHT;      break;
     318           0 :         case WEIGHT_SEMILIGHT:  nWeight=W_FW_LIGHT;      break;
     319         752 :         case WEIGHT_NORMAL:     nWeight=W_FW_NORMAL;     break;
     320           0 :         case WEIGHT_MEDIUM:     nWeight=W_FW_MEDIUM;     break;
     321           0 :         case WEIGHT_SEMIBOLD:   nWeight=W_FW_SEMIBOLD;   break;
     322           0 :         case WEIGHT_BOLD:       nWeight=W_FW_BOLD;       break;
     323           0 :         case WEIGHT_ULTRABOLD:  nWeight=W_FW_ULTRABOLD;  break;
     324           0 :         case WEIGHT_BLACK:      nWeight=W_FW_BLACK;      break;
     325          70 :         default:                nWeight=W_FW_DONTCARE;
     326             :     }
     327         822 :     pWMF->WriteUInt16( nWeight );
     328             : 
     329         822 :     if (rFont.GetItalic()==ITALIC_NONE)       pWMF->WriteUChar( 0 ); else  pWMF->WriteUChar( 1 );
     330         822 :     if (rFont.GetUnderline()==UNDERLINE_NONE) pWMF->WriteUChar( 0 ); else  pWMF->WriteUChar( 1 );
     331         822 :     if (rFont.GetStrikeout()==STRIKEOUT_NONE) pWMF->WriteUChar( 0 ); else  pWMF->WriteUChar( 1 );
     332             : 
     333         822 :     rtl_TextEncoding  eFontNameEncoding = rFont.GetCharSet();
     334         822 :     sal_uInt8         nCharSet = rtl_getBestWindowsCharsetFromTextEncoding( eFontNameEncoding );
     335         822 :     if ( eFontNameEncoding == RTL_TEXTENCODING_SYMBOL )
     336           0 :         eFontNameEncoding = RTL_TEXTENCODING_MS_1252;
     337         822 :     if ( nCharSet == 1 )
     338           0 :         nCharSet = W_ANSI_CHARSET;
     339         822 :     pWMF->WriteUChar( nCharSet );
     340             : 
     341         822 :     pWMF->WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
     342             : 
     343         822 :     switch (rFont.GetPitch()) {
     344           0 :         case PITCH_FIXED:    nPitchFamily=W_FIXED_PITCH;    break;
     345           4 :         case PITCH_VARIABLE: nPitchFamily=W_VARIABLE_PITCH; break;
     346         818 :         default:             nPitchFamily=W_DEFAULT_PITCH;
     347             :     }
     348         822 :     switch (rFont.GetFamily()) {
     349           0 :         case FAMILY_DECORATIVE: nPitchFamily|=W_FF_DECORATIVE; break;
     350           0 :         case FAMILY_MODERN:     nPitchFamily|=W_FF_MODERN;     break;
     351         484 :         case FAMILY_ROMAN:      nPitchFamily|=W_FF_ROMAN;      break;
     352           0 :         case FAMILY_SCRIPT:     nPitchFamily|=W_FF_SCRIPT;     break;
     353           0 :         case FAMILY_SWISS:      nPitchFamily|=W_FF_SWISS;      break;
     354         338 :         default:                nPitchFamily|=W_FF_DONTCARE;
     355             :     }
     356         822 :     pWMF->WriteUChar( nPitchFamily );
     357             : 
     358         822 :     OString aFontName(OUStringToOString(rFont.GetName(), eFontNameEncoding));
     359       27126 :     for ( i = 0; i < W_LF_FACESIZE; i++ )
     360             :     {
     361       26304 :         sal_Char nChar = ( i < aFontName.getLength() ) ? aFontName[i] : 0;
     362       26304 :         pWMF->WriteChar( nChar );
     363             :     }
     364         822 :     UpdateRecordHeader();
     365         822 : }
     366             : 
     367         356 : void WMFWriter::WMFRecord_CreatePenIndirect(const Color& rColor, const LineInfo& rLineInfo )
     368             : {
     369         356 :     WriteRecordHeader(0x00000008,W_META_CREATEPENINDIRECT);
     370         356 :     sal_uInt16 nStyle = rColor == Color( COL_TRANSPARENT ) ? W_PS_NULL : W_PS_SOLID;
     371         356 :     switch( rLineInfo.GetStyle() )
     372             :     {
     373             :         case LINE_DASH :
     374             :         {
     375           0 :             if ( rLineInfo.GetDotCount() )
     376             :             {
     377           0 :                 if ( !rLineInfo.GetDashCount() )
     378           0 :                     nStyle = W_PS_DOT;
     379             :                 else
     380             :                 {
     381           0 :                     if ( rLineInfo.GetDotCount() == 1 )
     382           0 :                         nStyle = W_PS_DASHDOT;
     383             :                     else
     384           0 :                         nStyle = W_PS_DASHDOTDOT;
     385             :                 }
     386             :             }
     387             :             else
     388           0 :                 nStyle = W_PS_DASH;
     389             :         }
     390           0 :         break;
     391             :         case LINE_NONE :
     392           0 :             nStyle = W_PS_NULL;
     393           0 :         break;
     394             :         default:
     395         356 :         break;
     396             :     }
     397         356 :     pWMF->WriteUInt16( nStyle );
     398             : 
     399         356 :     WriteSize( Size( rLineInfo.GetWidth(), 0 ) );
     400         356 :     WriteColor( rColor );
     401         356 : }
     402             : 
     403        1324 : void WMFWriter::WMFRecord_DeleteObject(sal_uInt16 nObjectHandle)
     404             : {
     405        1324 :     WriteRecordHeader(0x00000004,W_META_DELETEOBJECT);
     406        1324 :     pWMF->WriteUInt16( nObjectHandle );
     407        1324 : }
     408             : 
     409           0 : void WMFWriter::WMFRecord_Ellipse(const Rectangle & rRect)
     410             : {
     411           0 :     WriteRecordHeader(0x00000007,W_META_ELLIPSE);
     412           0 :     WriteRectangle(rRect);
     413           0 : }
     414             : 
     415         244 : void WMFWriter::WMFRecord_Escape( sal_uInt32 nEsc, sal_uInt32 nLen, const sal_Int8* pData )
     416             : {
     417             : #ifdef OSL_BIGENDIAN
     418             :     sal_uInt32 nTmp = OSL_SWAPDWORD( nEsc );
     419             :     sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
     420             : #else
     421         244 :     sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
     422             : #endif
     423         244 :     if ( nLen )
     424         244 :         nCheckSum = rtl_crc32( nCheckSum, pData, nLen );
     425             : 
     426         244 :     WriteRecordHeader( 3 + 9 + ( ( nLen + 1 ) >> 1 ), W_META_ESCAPE );
     427         244 :     pWMF->WriteUInt16( W_MFCOMMENT )
     428         488 :          .WriteUInt16( ( nLen + 14 ) )  // we will always have a fourteen byte escape header:
     429         244 :          .WriteUInt16( 0x4f4f )         // OO
     430         244 :          .WriteUInt32( 0xa2c2a )        // evil magic number
     431         244 :          .WriteUInt32( nCheckSum )      // crc32 checksum about nEsc & pData
     432         488 :          .WriteUInt32( nEsc );          // escape number
     433         244 :     pWMF->Write( pData, nLen );
     434         244 :     if ( nLen & 1 )
     435           0 :         pWMF->WriteUChar( 0 );          // pad byte
     436         244 : }
     437             : 
     438             : /* if return value is true, then a complete unicode string and also a polygon replacement has been written,
     439             :     so there is no more action necessary
     440             : */
     441         686 : bool WMFWriter::WMFRecord_Escape_Unicode( const Point& rPoint, const OUString& rUniStr, const long* pDXAry )
     442             : {
     443         686 :     bool bEscapeUsed = false;
     444             : 
     445         686 :     sal_uInt32 i, nStringLen = rUniStr.getLength();
     446         686 :     if ( nStringLen )
     447             :     {
     448             :         // first we will check if a comment is necessary
     449         686 :         if ( aSrcFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL )     // symbol is always byte character, so there is no unicode loss
     450             :         {
     451         686 :             const sal_Unicode* pBuf = rUniStr.getStr();
     452         686 :             const rtl_TextEncoding aTextEncodingOrg = aSrcFont.GetCharSet();
     453         686 :             OString aByteStr(OUStringToOString(rUniStr, aTextEncodingOrg));
     454        1372 :             OUString aUniStr2(OStringToOUString(aByteStr, aTextEncodingOrg));
     455         686 :             const sal_Unicode* pConversion = aUniStr2.getStr();  // this is the unicode array after bytestring <-> unistring conversion
     456        1350 :             for ( i = 0; i < nStringLen; i++ )
     457             :             {
     458         778 :                 if ( *pBuf++ != *pConversion++ )
     459         114 :                     break;
     460             :             }
     461             : 
     462         686 :             if  ( i != nStringLen )                             // after conversion the characters are not original,
     463             :             {                                                   // try again, with determining a better charset from unicode char
     464         114 :                 pBuf = rUniStr.getStr();
     465         114 :                 const sal_Unicode* pCheckChar = pBuf;
     466         114 :                 rtl_TextEncoding aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the first character
     467         118 :                 for ( i = 1; i < nStringLen; i++)
     468             :                 {
     469           8 :                     if (aTextEncoding != aTextEncodingOrg) // found something
     470           4 :                         break;
     471           4 :                     pCheckChar++;
     472           4 :                     aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the next character
     473             :                 }
     474             : 
     475         114 :                 aByteStr = OUStringToOString(rUniStr,  aTextEncoding);
     476         114 :                 aUniStr2 = OStringToOUString(aByteStr, aTextEncoding);
     477         114 :                 pConversion = aUniStr2.getStr(); // this is the unicode array after bytestring <-> unistring conversion
     478         188 :                 for ( i = 0; i < nStringLen; i++ )
     479             :                 {
     480         122 :                     if ( *pBuf++ != *pConversion++ )
     481          48 :                         break;
     482             :                 }
     483         114 :                 if (i == nStringLen)
     484             :                 {
     485          66 :                     aSrcFont.SetCharSet (aTextEncoding);
     486          66 :                     SetAllAttr();
     487             :                 }
     488             :             }
     489             : 
     490         686 :             if ( ( i != nStringLen ) || IsStarSymbol( aSrcFont.GetName() ) )    // after conversion the characters are not original, so we
     491             :             {                                                                   // will store the unicode string and a polypoly replacement
     492         244 :                 Color aOldFillColor( aSrcFillColor );
     493         244 :                 Color aOldLineColor( aSrcLineColor );
     494         244 :                 aSrcLineInfo  = LineInfo();
     495         244 :                 aSrcFillColor = aSrcTextColor;
     496         244 :                 aSrcLineColor = Color( COL_TRANSPARENT );
     497         244 :                 SetLineAndFillAttr();
     498         244 :                 pVirDev->SetFont( aSrcFont );
     499         244 :                 std::vector<tools::PolyPolygon> aPolyPolyVec;
     500         244 :                 if ( pVirDev->GetTextOutlines( aPolyPolyVec, rUniStr ) )
     501             :                 {
     502         244 :                     sal_uInt32 nDXCount = pDXAry ? nStringLen : 0;
     503         244 :                     sal_uInt32 nSkipActions = aPolyPolyVec.size();
     504             :                     sal_Int32 nStrmLen = 8 +
     505         244 :                                            + sizeof( nStringLen ) + ( nStringLen * 2 )
     506         244 :                                            + sizeof( nDXCount ) + ( nDXCount * 4 )
     507         732 :                                            + sizeof( nSkipActions );
     508             : 
     509         244 :                     SvMemoryStream aMemoryStream( nStrmLen );
     510         244 :                     Point aPt( OutputDevice::LogicToLogic( rPoint, aSrcMapMode, aTargetMapMode ) );
     511         244 :                     aMemoryStream.WriteInt32( aPt.X() )
     512         488 :                                  .WriteInt32( aPt.Y() )
     513         244 :                                  .WriteUInt32( nStringLen );
     514         488 :                     for ( i = 0; i < nStringLen; i++ )
     515         244 :                         aMemoryStream.WriteUInt16( rUniStr[ i ] );
     516         244 :                     aMemoryStream.WriteUInt32( nDXCount );
     517         244 :                     for ( i = 0; i < nDXCount; i++ )
     518           0 :                         aMemoryStream.WriteInt32( pDXAry[ i ] );
     519         244 :                     aMemoryStream.WriteUInt32( nSkipActions );
     520         244 :                     WMFRecord_Escape( PRIVATE_ESCAPE_UNICODE, nStrmLen, (const sal_Int8*)aMemoryStream.GetData() );
     521             : 
     522         244 :                     std::vector<tools::PolyPolygon>::iterator aIter( aPolyPolyVec.begin() );
     523         732 :                     while ( aIter != aPolyPolyVec.end() )
     524             :                     {
     525         244 :                         tools::PolyPolygon aPolyPoly( *aIter++ );
     526         244 :                         aPolyPoly.Move( rPoint.X(), rPoint.Y() );
     527         244 :                         WMFRecord_PolyPolygon( aPolyPoly );
     528         244 :                     }
     529         244 :                     aSrcFillColor = aOldFillColor;
     530         244 :                     aSrcLineColor = aOldLineColor;
     531         244 :                     bEscapeUsed = true;
     532         244 :                 }
     533         686 :             }
     534             :         }
     535             :     }
     536         686 :     return bEscapeUsed;
     537             : }
     538             : 
     539         442 : void WMFWriter::WMFRecord_ExtTextOut( const Point& rPoint,
     540             :                                       const OUString& rString,
     541             :                                       const long* pDXAry )
     542             : {
     543         442 :     sal_Int32 nOriginalTextLen = rString.getLength();
     544             : 
     545         442 :     if ( (nOriginalTextLen <= 1) || (pDXAry == NULL) )
     546             :     {
     547         396 :         WMFRecord_TextOut(rPoint, rString);
     548         838 :         return;
     549             :     }
     550          46 :     rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
     551          46 :     OString aByteString(OUStringToOString(rString, eChrSet));
     552          46 :     TrueExtTextOut(rPoint, rString, aByteString, pDXAry);
     553             : }
     554             : 
     555          46 : void WMFWriter::TrueExtTextOut( const Point& rPoint, const OUString& rString,
     556             :                                 const OString& rByteString, const long* pDXAry )
     557             : {
     558          46 :     WriteRecordHeader( 0, W_META_EXTTEXTOUT );
     559          46 :     WritePointYX( rPoint );
     560          46 :     sal_uInt16 nNewTextLen = static_cast<sal_uInt16>(rByteString.getLength());
     561          46 :     pWMF->WriteUInt16( nNewTextLen ).WriteUInt16( 0 );
     562          46 :     write_uInt8s_FromOString(*pWMF, rByteString, nNewTextLen);
     563          46 :     if ( nNewTextLen & 1 )
     564          30 :         pWMF->WriteUChar( 0 );
     565             : 
     566          46 :     sal_Int32 nOriginalTextLen = rString.getLength();
     567          46 :     boost::scoped_array<sal_Int16> pConvertedDXAry(new sal_Int16[ nOriginalTextLen ]);
     568          46 :     sal_Int32 j = 0;
     569          46 :     pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ 0 ] );
     570          92 :     for (sal_uInt16 i = 1; i < ( nOriginalTextLen - 1 ); ++i)
     571          46 :         pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ i ] - pDXAry[ i - 1 ] );
     572          46 :     pConvertedDXAry[ j ] = (sal_Int16)ScaleWidth( pDXAry[ nOriginalTextLen - 2 ] / ( nOriginalTextLen - 1 ) );
     573             : 
     574         184 :     for (sal_uInt16 i = 0; i < nOriginalTextLen; ++i)
     575             :     {
     576         138 :         sal_Int16 nDx = pConvertedDXAry[ i ];
     577         138 :         pWMF->WriteInt16( nDx );
     578         138 :         if ( nOriginalTextLen < nNewTextLen )
     579             :         {
     580           0 :             sal_Unicode nUniChar = rString[i];
     581           0 :             OString aTemp(&nUniChar, 1, aSrcFont.GetCharSet());
     582           0 :             j = aTemp.getLength();
     583           0 :             while ( --j > 0 )
     584           0 :                 pWMF->WriteUInt16( 0 );
     585             :         }
     586             :     }
     587          46 :     pConvertedDXAry.reset();
     588          46 :     UpdateRecordHeader();
     589          46 : }
     590             : 
     591           0 : void WMFWriter::WMFRecord_LineTo(const Point & rPoint)
     592             : {
     593           0 :     WriteRecordHeader(0x00000005,W_META_LINETO);
     594           0 :     WritePointYX(rPoint);
     595           0 : }
     596             : 
     597           0 : void WMFWriter::WMFRecord_MoveTo(const Point & rPoint)
     598             : {
     599           0 :     WriteRecordHeader(0x00000005,W_META_MOVETO);
     600           0 :     WritePointYX(rPoint);
     601           0 : }
     602             : 
     603           0 : void WMFWriter::WMFRecord_Pie(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
     604             : {
     605           0 :     WriteRecordHeader(0x0000000b,W_META_PIE);
     606           0 :     WritePointYX(rEndPt);
     607           0 :     WritePointYX(rStartPt);
     608           0 :     WriteRectangle(rRect);
     609           0 : }
     610             : 
     611           0 : void WMFWriter::WMFRecord_Polygon(const Polygon & rPoly)
     612             : {
     613             :     sal_uInt16 nSize,i;
     614             : 
     615           0 :     Polygon aSimplePoly;
     616           0 :     if ( rPoly.HasFlags() )
     617           0 :         rPoly.AdaptiveSubdivide( aSimplePoly );
     618             :     else
     619           0 :         aSimplePoly = rPoly;
     620           0 :     nSize = aSimplePoly.GetSize();
     621           0 :     WriteRecordHeader(((sal_uLong)nSize)*2+4,W_META_POLYGON);
     622           0 :     pWMF->WriteUInt16( nSize );
     623           0 :     for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
     624           0 : }
     625             : 
     626           0 : void WMFWriter::WMFRecord_PolyLine(const Polygon & rPoly)
     627             : {
     628             :     sal_uInt16 nSize,i;
     629           0 :     Polygon aSimplePoly;
     630           0 :     if ( rPoly.HasFlags() )
     631           0 :         rPoly.AdaptiveSubdivide( aSimplePoly );
     632             :     else
     633           0 :         aSimplePoly = rPoly;
     634           0 :     nSize=aSimplePoly.GetSize();
     635           0 :     WriteRecordHeader(((sal_uLong)nSize)*2+4,W_META_POLYLINE);
     636           0 :     pWMF->WriteUInt16( nSize );
     637           0 :     for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
     638           0 : }
     639             : 
     640         244 : void WMFWriter::WMFRecord_PolyPolygon(const tools::PolyPolygon & rPolyPoly)
     641             : {
     642             :     const Polygon * pPoly;
     643             :     sal_uInt16 nCount,nSize,i,j;
     644             : 
     645         244 :     nCount=rPolyPoly.Count();
     646         244 :     tools::PolyPolygon aSimplePolyPoly( rPolyPoly );
     647         556 :     for ( i = 0; i < nCount; i++ )
     648             :     {
     649         312 :         if ( aSimplePolyPoly[ i ].HasFlags() )
     650             :         {
     651         118 :             Polygon aSimplePoly;
     652         118 :             aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly );
     653         118 :             aSimplePolyPoly[ i ] = aSimplePoly;
     654             :         }
     655             :     }
     656         244 :     WriteRecordHeader(0,W_META_POLYPOLYGON);
     657         244 :     pWMF->WriteUInt16( nCount );
     658         244 :     for (i=0; i<nCount; i++) pWMF->WriteUInt16( (aSimplePolyPoly.GetObject(i).GetSize()) );
     659         556 :     for (i=0; i<nCount; i++) {
     660         312 :         pPoly=&(aSimplePolyPoly.GetObject(i));
     661         312 :         nSize=pPoly->GetSize();
     662         312 :         for (j=0; j<nSize; j++) WritePointXY(pPoly->GetPoint(j));
     663             :     }
     664         244 :     UpdateRecordHeader();
     665         244 : }
     666             : 
     667          40 : void WMFWriter::WMFRecord_Rectangle(const Rectangle & rRect)
     668             : {
     669          40 :     WriteRecordHeader( 0x00000007,W_META_RECTANGLE );
     670          40 :     WriteRectangle( rRect );
     671          40 : }
     672             : 
     673         796 : void WMFWriter::WMFRecord_RestoreDC()
     674             : {
     675         796 :     WriteRecordHeader(0x00000004,W_META_RESTOREDC);
     676         796 :     pWMF->WriteInt16( -1 );
     677         796 : }
     678             : 
     679           0 : void WMFWriter::WMFRecord_RoundRect(const Rectangle & rRect, long nHorzRound, long nVertRound)
     680             : {
     681           0 :     WriteRecordHeader(0x00000009,W_META_ROUNDRECT);
     682           0 :     WriteHeightWidth(Size(nHorzRound,nVertRound));
     683           0 :     WriteRectangle(rRect);
     684           0 : }
     685             : 
     686         796 : void WMFWriter::WMFRecord_SaveDC()
     687             : {
     688         796 :     WriteRecordHeader(0x00000003,W_META_SAVEDC);
     689         796 : }
     690             : 
     691        1534 : void WMFWriter::WMFRecord_SelectObject(sal_uInt16 nObjectHandle)
     692             : {
     693        1534 :     WriteRecordHeader(0x00000004,W_META_SELECTOBJECT);
     694        1534 :     pWMF->WriteUInt16( nObjectHandle );
     695        1534 : }
     696             : 
     697          70 : void WMFWriter::WMFRecord_SetBkMode(bool bTransparent)
     698             : {
     699          70 :     WriteRecordHeader(0x00000004,W_META_SETBKMODE);
     700          70 :     if (bTransparent) pWMF->WriteUInt16( W_TRANSPARENT );
     701           0 :     else                    pWMF->WriteUInt16( W_OPAQUE );
     702          70 : }
     703             : 
     704          70 : void WMFWriter::WMFRecord_SetStretchBltMode()
     705             : {
     706          70 :     WriteRecordHeader( 0x00000004, W_META_SETSTRETCHBLTMODE );
     707          70 :     pWMF->WriteUInt16( 3 ); // STRETCH_DELETESCANS
     708          70 : }
     709             : 
     710           0 : void WMFWriter::WMFRecord_SetPixel(const Point & rPoint, const Color & rColor)
     711             : {
     712           0 :     WriteRecordHeader(0x00000007,W_META_SETPIXEL);
     713           0 :     WriteColor(rColor);
     714           0 :     WritePointYX(rPoint);
     715           0 : }
     716             : 
     717          70 : void WMFWriter::WMFRecord_SetROP2(RasterOp eROP)
     718             : {
     719             :     sal_uInt16 nROP2;
     720             : 
     721          70 :     switch (eROP) {
     722           0 :         case ROP_INVERT: nROP2=W_R2_NOT;        break;
     723           0 :         case ROP_XOR:    nROP2=W_R2_XORPEN;     break;
     724          70 :         default:         nROP2=W_R2_COPYPEN;
     725             :     }
     726          70 :     WriteRecordHeader(0x00000004,W_META_SETROP2);
     727          70 :     pWMF->WriteUInt16( nROP2 );
     728          70 : }
     729             : 
     730          74 : void WMFWriter::WMFRecord_SetTextAlign(FontAlign eFontAlign, sal_uInt32 eHorTextAlign)
     731             : {
     732             :     sal_uInt16 nAlign;
     733             : 
     734          74 :     switch (eFontAlign) {
     735           4 :         case ALIGN_TOP:    nAlign=W_TA_TOP; break;
     736           0 :         case ALIGN_BOTTOM: nAlign=W_TA_BOTTOM; break;
     737          70 :         default:           nAlign=W_TA_BASELINE;
     738             :     }
     739          74 :     nAlign|=eHorTextAlign;
     740          74 :     nAlign|=W_TA_NOUPDATECP;
     741             : 
     742          74 :     WriteRecordHeader(0x00000004,W_META_SETTEXTALIGN);
     743          74 :     pWMF->WriteUInt16( nAlign );
     744          74 : }
     745             : 
     746         756 : void WMFWriter::WMFRecord_SetTextColor(const Color & rColor)
     747             : {
     748         756 :     WriteRecordHeader(0x00000005,W_META_SETTEXTCOLOR);
     749         756 :     WriteColor(rColor);
     750         756 : }
     751             : 
     752          70 : void WMFWriter::WMFRecord_SetWindowExt(const Size & rSize)
     753             : {
     754          70 :     WriteRecordHeader(0x00000005,W_META_SETWINDOWEXT);
     755          70 :     WriteHeightWidth(rSize);
     756          70 : }
     757             : 
     758          70 : void WMFWriter::WMFRecord_SetWindowOrg(const Point & rPoint)
     759             : {
     760          70 :     WriteRecordHeader(0x00000005,W_META_SETWINDOWORG);
     761          70 :     WritePointYX(rPoint);
     762          70 : }
     763             : 
     764          16 : void WMFWriter::WMFRecord_StretchDIB( const Point & rPoint, const Size & rSize,
     765             :                                       const Bitmap & rBitmap, sal_uInt32 nROP )
     766             : {
     767             :     sal_uLong nPosAnf,nPosEnd;
     768             : 
     769          16 :     nActBitmapPercent=50;
     770          16 :     MayCallback();
     771             : 
     772          16 :     WriteRecordHeader(0x00000000,W_META_STRETCHDIB);
     773             : 
     774             :     // The sequence in the metafile should be:
     775             :     // some parameters (length 22), then the bitmap without FILEHEADER.
     776             :     // As *pWMF << rBitmap generates a FILEHEADER of size 14,
     777             :     // we first write the bitmap at the right position
     778             :     // and overwrite later the FILEHEADER with the parameters.
     779          16 :     nPosAnf=pWMF->Tell(); // remember position, where parameters should be stored
     780          16 :     pWMF->WriteInt32( 0 ).WriteInt32( 0 ); // replenish 8 bytes (these 8 bytes +
     781             :                                            // 14 bytes superfluous FILEHEADER
     782             :                                            // = 22 bytes parameter)
     783             : 
     784             :     // write bitmap
     785          16 :     WriteDIB(rBitmap, *pWMF, false, true);
     786             : 
     787             :     // write the parameters:
     788          16 :     nPosEnd=pWMF->Tell();
     789          16 :     pWMF->Seek(nPosAnf);
     790             : 
     791             :     // determine raster-op, if nothing was passed
     792          16 :     if( !nROP )
     793             :     {
     794           4 :         switch( eSrcRasterOp )
     795             :         {
     796           0 :             case ROP_INVERT: nROP = W_DSTINVERT; break;
     797           0 :             case ROP_XOR:    nROP = W_SRCINVERT; break;
     798           4 :             default:         nROP = W_SRCCOPY;
     799             :         }
     800             :     }
     801             : 
     802          16 :     pWMF->WriteUInt32( nROP ).             WriteInt16( 0 ).             WriteInt16( rBitmap.GetSizePixel().Height() ).             WriteInt16( rBitmap.GetSizePixel().Width() ).             WriteInt16( 0 ).             WriteInt16( 0 );
     803             : 
     804          16 :     WriteHeightWidth(rSize);
     805          16 :     WritePointYX(rPoint);
     806          16 :     pWMF->Seek(nPosEnd);
     807             : 
     808          16 :     UpdateRecordHeader();
     809             : 
     810          16 :     nWrittenBitmaps++;
     811          16 :     nActBitmapPercent=0;
     812          16 : }
     813             : 
     814         396 : void WMFWriter::WMFRecord_TextOut(const Point & rPoint, const OUString & rStr)
     815             : {
     816         396 :     rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
     817         396 :     OString aString(OUStringToOString(rStr, eChrSet));
     818         396 :     TrueTextOut(rPoint, aString);
     819         396 : }
     820             : 
     821         396 : void WMFWriter::TrueTextOut(const Point & rPoint, const OString& rString)
     822             : {
     823         396 :     WriteRecordHeader(0,W_META_TEXTOUT);
     824             : 
     825         396 :     write_uInt16_lenPrefixed_uInt8s_FromOString(*pWMF, rString);
     826         396 :     sal_Int32 nLen = rString.getLength();
     827         396 :     if ((nLen&1)!=0) pWMF->WriteUChar( 0 );
     828         396 :     WritePointYX(rPoint);
     829         396 :     UpdateRecordHeader();
     830         396 : }
     831             : 
     832          70 : void WMFWriter::WMFRecord_EndOfFile()
     833             : {
     834          70 :     WriteRecordHeader(0x00000003,0x0000);
     835          70 : }
     836             : 
     837          68 : void WMFWriter::WMFRecord_IntersectClipRect( const Rectangle& rRect )
     838             : {
     839          68 :     WriteRecordHeader( 0x00000007, W_META_INTERSECTCLIPRECT );
     840          68 :     WriteRectangle(rRect);
     841          68 : }
     842             : 
     843        1534 : sal_uInt16 WMFWriter::AllocHandle()
     844             : {
     845             :     sal_uInt16 i;
     846             : 
     847        3856 :     for (i=0; i<MAXOBJECTHANDLES; i++) {
     848        3856 :         if (!bHandleAllocated[i]) {
     849        1534 :             bHandleAllocated[i]=true;
     850        1534 :             return i;
     851             :         }
     852             :     }
     853           0 :     bStatus=false;
     854           0 :     return 0xffff;
     855             : }
     856             : 
     857        1324 : void WMFWriter::FreeHandle(sal_uInt16 nObjectHandle)
     858             : {
     859        1324 :     if (nObjectHandle<MAXOBJECTHANDLES) bHandleAllocated[nObjectHandle]=false;
     860        1324 : }
     861             : 
     862         356 : void WMFWriter::CreateSelectDeletePen( const Color& rColor, const LineInfo& rLineInfo )
     863             : {
     864             :     sal_uInt16 nOldHandle;
     865             : 
     866         356 :     nOldHandle=nDstPenHandle;
     867         356 :     nDstPenHandle=AllocHandle();
     868         356 :     WMFRecord_CreatePenIndirect( rColor, rLineInfo );
     869         356 :     WMFRecord_SelectObject(nDstPenHandle);
     870         356 :     if (nOldHandle<MAXOBJECTHANDLES) {
     871         286 :         WMFRecord_DeleteObject(nOldHandle);
     872         286 :         FreeHandle(nOldHandle);
     873             :     }
     874         356 : }
     875             : 
     876         822 : void WMFWriter::CreateSelectDeleteFont(const vcl::Font & rFont)
     877             : {
     878             :     sal_uInt16 nOldHandle;
     879             : 
     880         822 :     nOldHandle=nDstFontHandle;
     881         822 :     nDstFontHandle=AllocHandle();
     882         822 :     WMFRecord_CreateFontIndirect(rFont);
     883         822 :     WMFRecord_SelectObject(nDstFontHandle);
     884         822 :     if (nOldHandle<MAXOBJECTHANDLES) {
     885         752 :         WMFRecord_DeleteObject(nOldHandle);
     886         752 :         FreeHandle(nOldHandle);
     887             :     }
     888         822 : }
     889             : 
     890         356 : void WMFWriter::CreateSelectDeleteBrush(const Color& rColor)
     891             : {
     892             :     sal_uInt16 nOldHandle;
     893             : 
     894         356 :     nOldHandle=nDstBrushHandle;
     895         356 :     nDstBrushHandle=AllocHandle();
     896         356 :     WMFRecord_CreateBrushIndirect(rColor);
     897         356 :     WMFRecord_SelectObject(nDstBrushHandle);
     898         356 :     if (nOldHandle<MAXOBJECTHANDLES) {
     899         286 :         WMFRecord_DeleteObject(nOldHandle);
     900         286 :         FreeHandle(nOldHandle);
     901             :     }
     902         356 : }
     903             : 
     904        1832 : void WMFWriter::SetLineAndFillAttr()
     905             : {
     906        1832 :     if ( eDstROP2 != eSrcRasterOp )
     907             :     {
     908           0 :         eDstROP2=eSrcRasterOp;
     909           0 :         WMFRecord_SetROP2(eDstROP2);
     910             :     }
     911        1832 :     if ( ( aDstLineColor != aSrcLineColor ) || ( aDstLineInfo != aSrcLineInfo ) )
     912             :     {
     913         286 :         aDstLineColor = aSrcLineColor;
     914         286 :         aDstLineInfo  = aSrcLineInfo;
     915         286 :         CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
     916             :     }
     917        1832 :     if ( aDstFillColor != aSrcFillColor )
     918             :     {
     919         286 :         aDstFillColor = aSrcFillColor;
     920         286 :         CreateSelectDeleteBrush( aDstFillColor );
     921             :     }
     922        1832 :     if ( bDstIsClipping != bSrcIsClipping ||
     923           0 :         (bSrcIsClipping && aDstClipRegion!=aSrcClipRegion)) {
     924           0 :         bDstIsClipping=bSrcIsClipping;
     925           0 :         aDstClipRegion=aSrcClipRegion;
     926             :     }
     927        1832 : }
     928             : 
     929        1548 : void WMFWriter::SetAllAttr()
     930             : {
     931        1548 :     SetLineAndFillAttr();
     932        1548 :     if ( aDstTextColor != aSrcTextColor )
     933             :     {
     934         686 :         aDstTextColor = aSrcTextColor;
     935         686 :         WMFRecord_SetTextColor(aDstTextColor);
     936             :     }
     937        1548 :     if ( eDstTextAlign != eSrcTextAlign || eDstHorTextAlign != eSrcHorTextAlign )
     938             :     {
     939           4 :         eDstTextAlign = eSrcTextAlign;
     940           4 :         eDstHorTextAlign = eSrcHorTextAlign;
     941           4 :         WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
     942             :     }
     943        1548 :     if ( aDstFont != aSrcFont )
     944             :     {
     945         752 :         pVirDev->SetFont(aSrcFont);
     946         752 :         if ( aDstFont.GetName() != aSrcFont.GetName() )
     947             :         {
     948         686 :             FontCharMapPtr pFontCharMap;
     949         686 :             if ( pVirDev->GetFontCharMap( pFontCharMap ) )
     950             :             {
     951         686 :                 if ( ( pFontCharMap->GetFirstChar() & 0xff00 ) == 0xf000 )
     952           0 :                     aSrcFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
     953         686 :                 else if ( aSrcFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
     954           0 :                     aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
     955             :             }
     956             : 
     957         686 :             pFontCharMap = 0;
     958             :         }
     959             : 
     960         752 :         aDstFont = aSrcFont;
     961         752 :         CreateSelectDeleteFont(aDstFont);
     962             :     }
     963        1548 : }
     964             : 
     965           0 : void WMFWriter::HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
     966             : {
     967           0 :     if(rLinePolygon.count())
     968             :     {
     969           0 :         basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
     970           0 :         basegfx::B2DPolyPolygon aFillPolyPolygon;
     971             : 
     972           0 :         rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
     973             : 
     974           0 :         if(aLinePolyPolygon.count())
     975             :         {
     976           0 :             aSrcLineInfo = rInfo;
     977           0 :             SetLineAndFillAttr();
     978             : 
     979           0 :             for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
     980             :             {
     981           0 :                 const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
     982           0 :                 WMFRecord_PolyLine(Polygon(aCandidate));
     983           0 :             }
     984             :         }
     985             : 
     986           0 :         if(aFillPolyPolygon.count())
     987             :         {
     988           0 :             const Color aOldLineColor(aSrcLineColor);
     989           0 :             const Color aOldFillColor(aSrcFillColor);
     990             : 
     991           0 :             aSrcLineColor = Color( COL_TRANSPARENT );
     992           0 :             aSrcFillColor = aOldLineColor;
     993           0 :             SetLineAndFillAttr();
     994             : 
     995           0 :             for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
     996             :             {
     997           0 :                 const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
     998           0 :                 WMFRecord_Polygon(Polygon(aPolygon));
     999           0 :             }
    1000             : 
    1001           0 :             aSrcLineColor = aOldLineColor;
    1002           0 :             aSrcFillColor = aOldFillColor;
    1003           0 :             SetLineAndFillAttr();
    1004           0 :         }
    1005             :     }
    1006           0 : }
    1007             : 
    1008          70 : void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
    1009             : {
    1010             :     MetaAction* pMA;
    1011             : 
    1012          70 :     if( bStatus )
    1013             :     {
    1014          70 :         size_t nACount = rMTF.GetActionSize();
    1015             : 
    1016          70 :         WMFRecord_SetStretchBltMode();
    1017             : 
    1018        5790 :         for( size_t nA = 0; nA < nACount; nA++ )
    1019             :         {
    1020        5720 :             pMA = rMTF.GetAction( nA );
    1021             : 
    1022        5720 :             switch( pMA->GetType() )
    1023             :             {
    1024             :                 case META_PIXEL_ACTION:
    1025             :                 {
    1026           0 :                     const MetaPixelAction* pA = static_cast<const MetaPixelAction *>(pMA);
    1027           0 :                     aSrcLineInfo = LineInfo();
    1028           0 :                     SetLineAndFillAttr();
    1029           0 :                     WMFRecord_SetPixel( pA->GetPoint(), pA->GetColor() );
    1030             :                 }
    1031           0 :                 break;
    1032             : 
    1033             :                 case META_POINT_ACTION:
    1034             :                 {
    1035           0 :                     const MetaPointAction*  pA = static_cast<const MetaPointAction*>(pMA);
    1036           0 :                     const Point&            rPt = pA->GetPoint();
    1037           0 :                     aSrcLineInfo = LineInfo();
    1038           0 :                     SetLineAndFillAttr();
    1039           0 :                     WMFRecord_MoveTo( rPt);
    1040           0 :                     WMFRecord_LineTo( rPt );
    1041             :                 }
    1042           0 :                 break;
    1043             : 
    1044             :                 case META_LINE_ACTION:
    1045             :                 {
    1046           0 :                     const MetaLineAction* pA = static_cast<const MetaLineAction *>(pMA);
    1047           0 :                     if(pA->GetLineInfo().IsDefault())
    1048             :                     {
    1049           0 :                         aSrcLineInfo = pA->GetLineInfo();
    1050           0 :                         SetLineAndFillAttr();
    1051           0 :                         WMFRecord_MoveTo( pA->GetStartPoint() );
    1052           0 :                         WMFRecord_LineTo( pA->GetEndPoint() );
    1053             :                     }
    1054             :                     else
    1055             :                     {
    1056             :                         // LineInfo used; handle Dash/Dot and fat lines
    1057           0 :                         basegfx::B2DPolygon aPolygon;
    1058           0 :                         aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
    1059           0 :                         aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
    1060           0 :                         HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
    1061             :                     }
    1062             :                 }
    1063           0 :                 break;
    1064             : 
    1065             :                 case META_RECT_ACTION:
    1066             :                 {
    1067          40 :                     const MetaRectAction* pA = static_cast<const MetaRectAction*>(pMA);
    1068          40 :                     aSrcLineInfo = LineInfo();
    1069          40 :                     SetLineAndFillAttr();
    1070          40 :                     WMFRecord_Rectangle( pA->GetRect() );
    1071             :                 }
    1072          40 :                 break;
    1073             : 
    1074             :                 case META_ROUNDRECT_ACTION:
    1075             :                 {
    1076           0 :                     const MetaRoundRectAction* pA = static_cast<const MetaRoundRectAction*>(pMA);
    1077           0 :                     aSrcLineInfo = LineInfo();
    1078           0 :                     SetLineAndFillAttr();
    1079           0 :                     WMFRecord_RoundRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
    1080             :                 }
    1081           0 :                 break;
    1082             : 
    1083             :                 case META_ELLIPSE_ACTION:
    1084             :                 {
    1085           0 :                     const MetaEllipseAction* pA = static_cast<const MetaEllipseAction*>(pMA);
    1086           0 :                     aSrcLineInfo = LineInfo();
    1087           0 :                     SetLineAndFillAttr();
    1088           0 :                     WMFRecord_Ellipse( pA->GetRect() );
    1089             :                 }
    1090           0 :                 break;
    1091             : 
    1092             :                 case META_ARC_ACTION:
    1093             :                 {
    1094           0 :                     const MetaArcAction* pA = static_cast<const MetaArcAction*>(pMA);
    1095           0 :                     aSrcLineInfo = LineInfo();
    1096           0 :                     SetLineAndFillAttr();
    1097           0 :                     WMFRecord_Arc( pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint() );
    1098             :                 }
    1099           0 :                 break;
    1100             : 
    1101             :                 case META_PIE_ACTION:
    1102             :                 {
    1103           0 :                     const MetaPieAction* pA = static_cast<const MetaPieAction*>(pMA);
    1104           0 :                     aSrcLineInfo = LineInfo();
    1105           0 :                     SetLineAndFillAttr();
    1106           0 :                     WMFRecord_Pie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
    1107             :                 }
    1108           0 :                 break;
    1109             : 
    1110             :                 case META_CHORD_ACTION:
    1111             :                 {
    1112           0 :                     const MetaChordAction* pA = static_cast<const MetaChordAction*>(pMA);
    1113           0 :                     aSrcLineInfo = LineInfo();
    1114           0 :                     SetLineAndFillAttr();
    1115           0 :                     WMFRecord_Chord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
    1116             :                 }
    1117           0 :                 break;
    1118             : 
    1119             :                 case META_POLYLINE_ACTION:
    1120             :                 {
    1121           0 :                     const MetaPolyLineAction* pA = static_cast<const MetaPolyLineAction*>(pMA);
    1122           0 :                     const Polygon&              rPoly = pA->GetPolygon();
    1123             : 
    1124           0 :                     if( rPoly.GetSize() )
    1125             :                     {
    1126           0 :                         if(pA->GetLineInfo().IsDefault())
    1127             :                         {
    1128           0 :                             aSrcLineInfo = pA->GetLineInfo();
    1129           0 :                             SetLineAndFillAttr();
    1130           0 :                             WMFRecord_PolyLine( rPoly );
    1131             :                         }
    1132             :                         else
    1133             :                         {
    1134             :                             // LineInfo used; handle Dash/Dot and fat lines
    1135           0 :                             HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
    1136             :                         }
    1137             :                     }
    1138             :                 }
    1139           0 :                 break;
    1140             : 
    1141             :                 case META_POLYGON_ACTION:
    1142             :                 {
    1143           0 :                     const MetaPolygonAction* pA = static_cast<const MetaPolygonAction*>(pMA);
    1144           0 :                     aSrcLineInfo = LineInfo();
    1145           0 :                     SetLineAndFillAttr();
    1146           0 :                     WMFRecord_Polygon( pA->GetPolygon() );
    1147             :                 }
    1148           0 :                 break;
    1149             : 
    1150             :                 case META_POLYPOLYGON_ACTION:
    1151             :                 {
    1152           0 :                     const MetaPolyPolygonAction* pA = static_cast<const MetaPolyPolygonAction*>(pMA);
    1153           0 :                     aSrcLineInfo = LineInfo();
    1154           0 :                     SetLineAndFillAttr();
    1155           0 :                     WMFRecord_PolyPolygon( pA->GetPolyPolygon() );
    1156             :                 }
    1157           0 :                 break;
    1158             : 
    1159             :                 case META_TEXTRECT_ACTION:
    1160             :                 {
    1161           0 :                     const MetaTextRectAction * pA = static_cast<const MetaTextRectAction*>(pMA);
    1162           0 :                     OUString aTemp( pA->GetText() );
    1163           0 :                     aSrcLineInfo = LineInfo();
    1164           0 :                     SetAllAttr();
    1165             : 
    1166           0 :                     Point aPos( pA->GetRect().TopLeft() );
    1167           0 :                     if ( !WMFRecord_Escape_Unicode( aPos, aTemp, NULL ) )
    1168           0 :                         WMFRecord_TextOut( aPos, aTemp );
    1169             :                 }
    1170           0 :                 break;
    1171             : 
    1172             :                 case META_TEXT_ACTION:
    1173             :                 {
    1174           0 :                     const MetaTextAction * pA = static_cast<const MetaTextAction*>(pMA);
    1175           0 :                     OUString aTemp = pA->GetText().copy( pA->GetIndex(), std::min<sal_Int32>(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
    1176           0 :                     aSrcLineInfo = LineInfo();
    1177           0 :                     SetAllAttr();
    1178           0 :                     if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, NULL ) )
    1179           0 :                         WMFRecord_TextOut( pA->GetPoint(), aTemp );
    1180             :                 }
    1181           0 :                 break;
    1182             : 
    1183             :                 case META_TEXTARRAY_ACTION:
    1184             :                 {
    1185           4 :                     const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pMA);
    1186             : 
    1187           4 :                     OUString aTemp = pA->GetText().copy( pA->GetIndex(), std::min<sal_Int32>(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
    1188           4 :                     aSrcLineInfo = LineInfo();
    1189           4 :                     SetAllAttr();
    1190           4 :                     if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pA->GetDXArray() ) )
    1191           4 :                         WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pA->GetDXArray() );
    1192             :                 }
    1193           4 :                 break;
    1194             : 
    1195             :                 case META_STRETCHTEXT_ACTION:
    1196             :                 {
    1197         688 :                     const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction *>(pMA);
    1198         688 :                     OUString aTemp = pA->GetText().copy( pA->GetIndex(), std::min<sal_Int32>(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
    1199             : 
    1200             :                     sal_uInt16 nLen,i;
    1201             :                     sal_Int32 nNormSize;
    1202             : 
    1203         688 :                     pVirDev->SetFont( aSrcFont );
    1204         688 :                     nLen = aTemp.getLength();
    1205        1376 :                     boost::scoped_array<long> pDXAry(nLen ? new long[ nLen ] : NULL);
    1206         688 :                     nNormSize = pVirDev->GetTextArray( aTemp, pDXAry.get() );
    1207         688 :                     if (nLen && nNormSize == 0)
    1208             :                     {
    1209             :                         OSL_FAIL("Impossible div by 0 action: MetaStretchTextAction!");
    1210             :                     }
    1211             :                     else
    1212             :                     {
    1213         778 :                         for ( i = 0; i < ( nLen - 1 ); i++ )
    1214          96 :                             pDXAry[ i ] = pDXAry[ i ] * (sal_Int32)pA->GetWidth() / nNormSize;
    1215         682 :                         if ( ( nLen <= 1 ) || ( (sal_Int32)pA->GetWidth() == nNormSize ) )
    1216         636 :                             pDXAry.reset();
    1217         682 :                         aSrcLineInfo = LineInfo();
    1218         682 :                         SetAllAttr();
    1219         682 :                         if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pDXAry.get() ) )
    1220         438 :                             WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pDXAry.get() );
    1221         688 :                     }
    1222             :                 }
    1223         688 :                 break;
    1224             : 
    1225             :                 case META_BMP_ACTION:
    1226             :                 {
    1227           0 :                     const MetaBmpAction* pA = static_cast<const MetaBmpAction *>(pMA);
    1228           0 :                     WMFRecord_StretchDIB( pA->GetPoint(), pA->GetBitmap().GetSizePixel(), pA->GetBitmap() );
    1229             :                 }
    1230           0 :                 break;
    1231             : 
    1232             :                 case META_BMPSCALE_ACTION:
    1233             :                 {
    1234           4 :                     const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pMA);
    1235           4 :                     WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pA->GetBitmap() );
    1236             :                 }
    1237           4 :                 break;
    1238             : 
    1239             :                 case META_BMPSCALEPART_ACTION:
    1240             :                 {
    1241           0 :                     const MetaBmpScalePartAction*   pA = static_cast<const MetaBmpScalePartAction*>(pMA);
    1242           0 :                     Bitmap                          aTmp( pA->GetBitmap() );
    1243             : 
    1244           0 :                     if( aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
    1245           0 :                         WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aTmp );
    1246             :                 }
    1247           0 :                 break;
    1248             : 
    1249             :                 case META_BMPEX_ACTION:
    1250             :                 {
    1251           0 :                     const MetaBmpExAction*  pA = static_cast<const MetaBmpExAction *>(pMA);
    1252           0 :                     Bitmap                  aBmp( pA->GetBitmapEx().GetBitmap() );
    1253           0 :                     Bitmap                  aMsk( pA->GetBitmapEx().GetMask() );
    1254             : 
    1255           0 :                     if( !!aMsk )
    1256             :                     {
    1257           0 :                         aBmp.Replace( aMsk, COL_WHITE );
    1258           0 :                         aMsk.Invert();
    1259           0 :                         WMFRecord_StretchDIB( pA->GetPoint(), aMsk.GetSizePixel(), aBmp, W_SRCPAINT );
    1260           0 :                         WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp, W_SRCAND );
    1261             :                     }
    1262             :                     else
    1263           0 :                         WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp );
    1264             :                 }
    1265           0 :                 break;
    1266             : 
    1267             :                 case META_BMPEXSCALE_ACTION:
    1268             :                 {
    1269           6 :                     const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pMA);
    1270           6 :                     Bitmap                      aBmp( pA->GetBitmapEx().GetBitmap() );
    1271          12 :                     Bitmap                      aMsk( pA->GetBitmapEx().GetMask() );
    1272             : 
    1273           6 :                     if( !!aMsk )
    1274             :                     {
    1275           6 :                         aBmp.Replace( aMsk, COL_WHITE );
    1276           6 :                         aMsk.Invert();
    1277           6 :                         WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aMsk, W_SRCPAINT );
    1278           6 :                         WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp, W_SRCAND );
    1279             :                     }
    1280             :                     else
    1281           6 :                         WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp );
    1282             :                 }
    1283           6 :                 break;
    1284             : 
    1285             :                 case META_BMPEXSCALEPART_ACTION:
    1286             :                 {
    1287           0 :                     const MetaBmpExScalePartAction* pA = static_cast<const MetaBmpExScalePartAction*>(pMA);
    1288           0 :                     BitmapEx                        aBmpEx( pA->GetBitmapEx() );
    1289           0 :                     aBmpEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
    1290           0 :                     Bitmap                          aBmp( aBmpEx.GetBitmap() );
    1291           0 :                     Bitmap                          aMsk( aBmpEx.GetMask() );
    1292             : 
    1293           0 :                     if( !!aMsk )
    1294             :                     {
    1295           0 :                         aBmp.Replace( aMsk, COL_WHITE );
    1296           0 :                         aMsk.Invert();
    1297           0 :                         WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aMsk, W_SRCPAINT );
    1298           0 :                         WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp, W_SRCAND );
    1299             :                     }
    1300             :                     else
    1301           0 :                         WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
    1302             :                 }
    1303           0 :                 break;
    1304             : 
    1305             :                 case META_GRADIENT_ACTION:
    1306             :                 {
    1307           0 :                     const MetaGradientAction*   pA = static_cast<const MetaGradientAction*>(pMA);
    1308           0 :                     GDIMetaFile                 aTmpMtf;
    1309             : 
    1310           0 :                     pVirDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
    1311           0 :                     WriteRecords( aTmpMtf );
    1312             :                 }
    1313           0 :                 break;
    1314             : 
    1315             :                 case META_HATCH_ACTION:
    1316             :                 {
    1317           0 :                     const MetaHatchAction*  pA = static_cast<const MetaHatchAction*>(pMA);
    1318           0 :                     GDIMetaFile             aTmpMtf;
    1319             : 
    1320           0 :                     pVirDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
    1321           0 :                     WriteRecords( aTmpMtf );
    1322             :                 }
    1323           0 :                 break;
    1324             : 
    1325             :                 case META_WALLPAPER_ACTION:
    1326             :                 {
    1327           0 :                     const MetaWallpaperAction*  pA = static_cast<const MetaWallpaperAction*>(pMA);
    1328           0 :                     const Color&                rColor = pA->GetWallpaper().GetColor();
    1329           0 :                     const Color                 aOldLineColor( aSrcLineColor );
    1330           0 :                     const Color                 aOldFillColor( aSrcFillColor );
    1331             : 
    1332           0 :                     aSrcLineColor = rColor;
    1333           0 :                     aSrcFillColor = rColor;
    1334           0 :                     aSrcLineInfo = LineInfo();
    1335           0 :                     SetLineAndFillAttr();
    1336           0 :                     WMFRecord_Rectangle( pA->GetRect() );
    1337           0 :                     aSrcLineColor = aOldLineColor;
    1338           0 :                     aSrcFillColor = aOldFillColor;
    1339             :                 }
    1340           0 :                 break;
    1341             : 
    1342             :                 case META_ISECTRECTCLIPREGION_ACTION:
    1343             :                 {
    1344          68 :                     const MetaISectRectClipRegionAction* pA = static_cast<const MetaISectRectClipRegionAction*>(pMA);
    1345          68 :                     WMFRecord_IntersectClipRect( pA->GetRect() );
    1346             :                 }
    1347          68 :                 break;
    1348             : 
    1349             :                 case META_LINECOLOR_ACTION:
    1350             :                 {
    1351          40 :                     const MetaLineColorAction* pA = static_cast<const MetaLineColorAction*>(pMA);
    1352             : 
    1353          40 :                     if( pA->IsSetting() )
    1354           0 :                         aSrcLineColor = pA->GetColor();
    1355             :                     else
    1356          40 :                         aSrcLineColor = Color( COL_TRANSPARENT );
    1357             :                 }
    1358          40 :                 break;
    1359             : 
    1360             :                 case META_FILLCOLOR_ACTION:
    1361             :                 {
    1362          40 :                     const MetaFillColorAction* pA = static_cast<const MetaFillColorAction*>(pMA);
    1363             : 
    1364          40 :                     if( pA->IsSetting() )
    1365          38 :                         aSrcFillColor = pA->GetColor();
    1366             :                     else
    1367           2 :                         aSrcFillColor = Color( COL_TRANSPARENT );
    1368             :                 }
    1369          40 :                 break;
    1370             : 
    1371             :                 case META_TEXTCOLOR_ACTION:
    1372             :                 {
    1373         738 :                     const MetaTextColorAction* pA = static_cast<const MetaTextColorAction*>(pMA);
    1374         738 :                     aSrcTextColor = pA->GetColor();
    1375             :                 }
    1376         738 :                 break;
    1377             : 
    1378             :                 case META_TEXTFILLCOLOR_ACTION:
    1379             :                 {
    1380         730 :                     const MetaTextFillColorAction* pA = static_cast<const MetaTextFillColorAction*>(pMA);
    1381         730 :                     if( pA->IsSetting() )
    1382           0 :                         aSrcFont.SetFillColor( pA->GetColor() );
    1383             :                     else
    1384         730 :                         aSrcFont.SetFillColor( Color( COL_TRANSPARENT ) );
    1385             :                 }
    1386         730 :                 break;
    1387             : 
    1388             :                 case META_TEXTALIGN_ACTION:
    1389             :                 {
    1390         728 :                     const MetaTextAlignAction* pA = static_cast<const MetaTextAlignAction*>(pMA);
    1391         728 :                     eSrcTextAlign = pA->GetTextAlign();
    1392             :                 }
    1393         728 :                 break;
    1394             : 
    1395             :                 case META_MAPMODE_ACTION:
    1396             :                 {
    1397           0 :                     const MetaMapModeAction* pA = static_cast<const MetaMapModeAction*>(pMA);
    1398             : 
    1399           0 :                     if (aSrcMapMode!=pA->GetMapMode())
    1400             :                     {
    1401           0 :                         if( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE )
    1402             :                         {
    1403           0 :                             MapMode aMM = pA->GetMapMode();
    1404           0 :                             Fraction aScaleX = aMM.GetScaleX();
    1405           0 :                             Fraction aScaleY = aMM.GetScaleY();
    1406             : 
    1407           0 :                             Point aOrigin = aSrcMapMode.GetOrigin();
    1408           0 :                             BigInt aX( aOrigin.X() );
    1409           0 :                             aX *= BigInt( aScaleX.GetDenominator() );
    1410           0 :                             if( aOrigin.X() >= 0 )
    1411           0 :                                 if( aScaleX.GetNumerator() >= 0 )
    1412           0 :                                     aX += BigInt( aScaleX.GetNumerator()/2 );
    1413             :                                 else
    1414           0 :                                     aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
    1415             :                             else
    1416           0 :                                 if( aScaleX.GetNumerator() >= 0 )
    1417           0 :                                     aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
    1418             :                                 else
    1419           0 :                                     aX += BigInt( aScaleX.GetNumerator()/2 );
    1420           0 :                             aX /= BigInt( aScaleX.GetNumerator() );
    1421           0 :                             aOrigin.X() = (long)aX + aMM.GetOrigin().X();
    1422           0 :                             BigInt aY( aOrigin.Y() );
    1423           0 :                             aY *= BigInt( aScaleY.GetDenominator() );
    1424           0 :                             if( aOrigin.Y() >= 0 )
    1425           0 :                                 if( aScaleY.GetNumerator() >= 0 )
    1426           0 :                                     aY += BigInt( aScaleY.GetNumerator()/2 );
    1427             :                                 else
    1428           0 :                                     aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
    1429             :                             else
    1430           0 :                                 if( aScaleY.GetNumerator() >= 0 )
    1431           0 :                                     aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
    1432             :                                 else
    1433           0 :                                     aY += BigInt( aScaleY.GetNumerator()/2 );
    1434           0 :                             aY /= BigInt( aScaleY.GetNumerator() );
    1435           0 :                             aOrigin.Y() = (long)aY + aMM.GetOrigin().Y();
    1436           0 :                             aSrcMapMode.SetOrigin( aOrigin );
    1437             : 
    1438           0 :                             aScaleX *= aSrcMapMode.GetScaleX();
    1439           0 :                             aScaleY *= aSrcMapMode.GetScaleY();
    1440           0 :                             aSrcMapMode.SetScaleX( aScaleX );
    1441           0 :                             aSrcMapMode.SetScaleY( aScaleY );
    1442             :                         }
    1443             :                         else
    1444           0 :                             aSrcMapMode=pA->GetMapMode();
    1445             :                     }
    1446             :                 }
    1447           0 :                 break;
    1448             : 
    1449             :                 case META_FONT_ACTION:
    1450             :                 {
    1451         728 :                     const MetaFontAction* pA = static_cast<const MetaFontAction*>(pMA);
    1452         728 :                     aSrcFont = pA->GetFont();
    1453             : 
    1454        1456 :                     if ( (aSrcFont.GetCharSet() == RTL_TEXTENCODING_DONTKNOW)
    1455         728 :                          || (aSrcFont.GetCharSet() == RTL_TEXTENCODING_UNICODE) )
    1456             :                     {
    1457         726 :                         aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
    1458             :                     }
    1459         728 :                     eSrcTextAlign = aSrcFont.GetAlign();
    1460         728 :                     aSrcTextColor = aSrcFont.GetColor();
    1461         728 :                     aSrcFont.SetAlign( ALIGN_BASELINE );
    1462         728 :                     aSrcFont.SetColor( COL_WHITE );
    1463             :                 }
    1464         728 :                 break;
    1465             : 
    1466             :                 case META_PUSH_ACTION:
    1467             :                 {
    1468         796 :                     const MetaPushAction* pA = static_cast<const MetaPushAction*>(pMA);
    1469             : 
    1470         796 :                     WMFWriterAttrStackMember* pAt = new WMFWriterAttrStackMember;
    1471         796 :                     pAt->nFlags = pA->GetFlags();
    1472         796 :                     pAt->aClipRegion = aSrcClipRegion;
    1473         796 :                     pAt->aLineColor=aSrcLineColor;
    1474         796 :                     pAt->aFillColor=aSrcFillColor;
    1475         796 :                     pAt->eRasterOp=eSrcRasterOp;
    1476         796 :                     pAt->aFont=aSrcFont;
    1477         796 :                     pAt->eTextAlign=eSrcTextAlign;
    1478         796 :                     pAt->aTextColor=aSrcTextColor;
    1479         796 :                     pAt->aMapMode=aSrcMapMode;
    1480         796 :                     pAt->aLineInfo=aDstLineInfo;
    1481         796 :                     pAt->pSucc=pAttrStack;
    1482         796 :                     pAttrStack=pAt;
    1483             : 
    1484         796 :                     SetAllAttr();           // update ( now all source attributes are equal to the destination attributes )
    1485         796 :                     WMFRecord_SaveDC();
    1486             : 
    1487             :                 }
    1488         796 :                 break;
    1489             : 
    1490             :                 case META_POP_ACTION:
    1491             :                 {
    1492         796 :                     WMFWriterAttrStackMember * pAt=pAttrStack;
    1493             : 
    1494         796 :                     if( pAt )
    1495             :                     {
    1496         796 :                         aDstLineInfo = pAt->aLineInfo;
    1497         796 :                         aDstLineColor = pAt->aLineColor;
    1498         796 :                         if ( pAt->nFlags & PushFlags::LINECOLOR )
    1499         786 :                             aSrcLineColor = pAt->aLineColor;
    1500         796 :                         aDstFillColor = pAt->aFillColor;
    1501         796 :                         if ( pAt->nFlags & PushFlags::FILLCOLOR )
    1502         786 :                             aSrcFillColor = pAt->aFillColor;
    1503         796 :                         eDstROP2 = pAt->eRasterOp;
    1504         796 :                         if ( pAt->nFlags & PushFlags::RASTEROP )
    1505          60 :                             eSrcRasterOp = pAt->eRasterOp;
    1506         796 :                         aDstFont = pAt->aFont;
    1507         796 :                         if ( pAt->nFlags & PushFlags::FONT )
    1508         786 :                             aSrcFont = pAt->aFont;
    1509         796 :                         eDstTextAlign = pAt->eTextAlign;
    1510         796 :                         if ( pAt->nFlags & ( PushFlags::FONT | PushFlags::TEXTALIGN ) )
    1511         786 :                             eSrcTextAlign = pAt->eTextAlign;
    1512         796 :                         aDstTextColor = pAt->aTextColor;
    1513         796 :                         if ( pAt->nFlags & ( PushFlags::FONT | PushFlags::TEXTCOLOR ) )
    1514         786 :                             aSrcTextColor = pAt->aTextColor;
    1515         796 :                         if ( pAt->nFlags & PushFlags::MAPMODE )
    1516         786 :                             aSrcMapMode = pAt->aMapMode;
    1517         796 :                         aDstClipRegion = pAt->aClipRegion;
    1518         796 :                         if ( pAt->nFlags & PushFlags::CLIPREGION )
    1519          70 :                             aSrcClipRegion = pAt->aClipRegion;
    1520             : 
    1521         796 :                         WMFRecord_RestoreDC();
    1522         796 :                         pAttrStack = pAt->pSucc;
    1523         796 :                         delete pAt;
    1524             :                     }
    1525             :                 }
    1526         796 :                 break;
    1527             : 
    1528             :                 case META_EPS_ACTION :
    1529             :                 {
    1530           0 :                     const MetaEPSAction* pA = static_cast<const MetaEPSAction*>(pMA);
    1531           0 :                     const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
    1532             : 
    1533           0 :                     size_t nCount = aGDIMetaFile.GetActionSize();
    1534           0 :                     for ( size_t i = 0; i < nCount; i++ )
    1535             :                     {
    1536           0 :                         const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
    1537           0 :                         if ( pMetaAct->GetType() == META_BMPSCALE_ACTION )
    1538             :                         {
    1539           0 :                             const MetaBmpScaleAction* pBmpScaleAction = static_cast<const MetaBmpScaleAction*>(pMetaAct);
    1540           0 :                             WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap() );
    1541           0 :                             break;
    1542             :                         }
    1543           0 :                     }
    1544             :                 }
    1545           0 :                 break;
    1546             : 
    1547             :                 case META_RASTEROP_ACTION:
    1548             :                 {
    1549          14 :                     const MetaRasterOpAction* pA = static_cast<const MetaRasterOpAction*>(pMA);
    1550          14 :                     eSrcRasterOp=pA->GetRasterOp();
    1551             :                 }
    1552          14 :                 break;
    1553             : 
    1554             :                 case META_TRANSPARENT_ACTION:
    1555             :                 {
    1556           0 :                     aSrcLineInfo = LineInfo();
    1557           0 :                     SetLineAndFillAttr();
    1558           0 :                     WMFRecord_PolyPolygon( static_cast<const MetaTransparentAction*>(pMA)->GetPolyPolygon() );
    1559             :                 }
    1560           0 :                 break;
    1561             : 
    1562             :                 case META_FLOATTRANSPARENT_ACTION:
    1563             :                 {
    1564           0 :                     const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pMA);
    1565             : 
    1566           0 :                     GDIMetaFile     aTmpMtf( pA->GetGDIMetaFile() );
    1567           0 :                     Point           aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
    1568           0 :                     const Size      aSrcSize( aTmpMtf.GetPrefSize() );
    1569           0 :                     const Point     aDestPt( pA->GetPoint() );
    1570           0 :                     const Size      aDestSize( pA->GetSize() );
    1571           0 :                     const double    fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
    1572           0 :                     const double    fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
    1573             :                     long            nMoveX, nMoveY;
    1574             : 
    1575           0 :                     aSrcLineInfo = LineInfo();
    1576           0 :                     SetAllAttr();
    1577             : 
    1578           0 :                     if( fScaleX != 1.0 || fScaleY != 1.0 )
    1579             :                     {
    1580           0 :                         aTmpMtf.Scale( fScaleX, fScaleY );
    1581           0 :                         aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
    1582             :                     }
    1583             : 
    1584           0 :                     nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
    1585             : 
    1586           0 :                     if( nMoveX || nMoveY )
    1587           0 :                         aTmpMtf.Move( nMoveX, nMoveY );
    1588             : 
    1589           0 :                     WriteRecords( aTmpMtf );
    1590             :                 }
    1591           0 :                 break;
    1592             : 
    1593             :                 case( META_LAYOUTMODE_ACTION ):
    1594             :                 {
    1595         120 :                     ComplexTextLayoutMode nLayoutMode = static_cast<const MetaLayoutModeAction*>(pMA)->GetLayoutMode();
    1596         120 :                     eSrcHorTextAlign = 0; // TA_LEFT
    1597         120 :                     if ((nLayoutMode & TEXT_LAYOUT_BIDI_RTL) != TEXT_LAYOUT_DEFAULT)
    1598             :                     {
    1599           0 :                         eSrcHorTextAlign = W_TA_RIGHT | W_TA_RTLREADING;
    1600             :                     }
    1601         120 :                     if ((nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_RIGHT) != TEXT_LAYOUT_DEFAULT)
    1602           0 :                         eSrcHorTextAlign |= W_TA_RIGHT;
    1603         120 :                     else if ((nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT) != TEXT_LAYOUT_DEFAULT)
    1604           0 :                         eSrcHorTextAlign &= ~W_TA_RIGHT;
    1605         120 :                     break;
    1606             :                 }
    1607             : 
    1608             :                 // Unsupported Actions
    1609             :                 case META_MASK_ACTION:
    1610             :                 case META_MASKSCALE_ACTION:
    1611             :                 case META_MASKSCALEPART_ACTION:
    1612             :                 {
    1613             :                     OSL_FAIL( "Unsupported action: MetaMask...Action!" );
    1614             :                 }
    1615           0 :                 break;
    1616             : 
    1617             :                 case META_CLIPREGION_ACTION:
    1618           0 :                 break;
    1619             : 
    1620             :                 case META_ISECTREGIONCLIPREGION_ACTION:
    1621             :                 {
    1622             :                     OSL_FAIL( "Unsupported action: MetaISectRegionClipRegionAction!" );
    1623             :                 }
    1624           0 :                 break;
    1625             : 
    1626             :                 case META_MOVECLIPREGION_ACTION:
    1627             :                 {
    1628             :                     OSL_FAIL( "Unsupported action: MetaMoveClipRegionAction!" );
    1629             :                 }
    1630           0 :                 break;
    1631             : 
    1632             :                 default:
    1633             :                 {
    1634             :                     OSL_FAIL( "Unsupported meta action!" );
    1635             :                 }
    1636         180 :                 break;
    1637             :           }
    1638             : 
    1639        5720 :           nWrittenActions++;
    1640        5720 :           MayCallback();
    1641             : 
    1642        5720 :           if (pWMF->GetError())
    1643           0 :             bStatus=false;
    1644             : 
    1645        5720 :           if(!bStatus)
    1646           0 :             break;
    1647             :         }
    1648             :     }
    1649          70 : }
    1650             : 
    1651          70 : void WMFWriter::WriteHeader( const GDIMetaFile &, bool bPlaceable )
    1652             : {
    1653          70 :     if( bPlaceable )
    1654             :     {
    1655             :         sal_uInt16  nCheckSum, nValue;
    1656          70 :         Size    aSize( OutputDevice::LogicToLogic(Size(1,1),MapMode(MAP_INCH), aTargetMapMode) );
    1657          70 :         sal_uInt16  nUnitsPerInch = (sal_uInt16) ( ( aSize.Width() + aSize.Height() ) >> 1 );
    1658             : 
    1659          70 :         nCheckSum=0;
    1660          70 :         nValue=0xcdd7;                              nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
    1661          70 :         nValue=0x9ac6;                              nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
    1662          70 :         nValue=0x0000;                              nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
    1663          70 :         nValue=0x0000;                              nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
    1664          70 :         nValue=0x0000;                              nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
    1665          70 :         nValue=(sal_uInt16) aTargetSize.Width();        nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
    1666          70 :         nValue=(sal_uInt16) aTargetSize.Height();       nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
    1667          70 :         nValue=nUnitsPerInch;                       nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
    1668          70 :         nValue=0x0000;                              nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
    1669          70 :         nValue=0x0000;                              nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
    1670          70 :         pWMF->WriteUInt16( nCheckSum );
    1671             :     }
    1672             : 
    1673          70 :     nMetafileHeaderPos=pWMF->Tell();
    1674          70 :     pWMF->WriteUInt16( 0x0001 )           // type: file
    1675          70 :          .WriteUInt16( 0x0009 )           // header length in words
    1676          70 :          .WriteUInt16( 0x0300 )           // Version as BCD number
    1677          70 :          .WriteUInt32( 0x00000000 )      // file length (without 1st header), is later corrected by UpdateHeader()
    1678          70 :          .WriteUInt16( MAXOBJECTHANDLES ) // maxmimum number of simultaneous objects
    1679          70 :          .WriteUInt32( 0x00000000 )      // maximum record length, is later corrected by UpdateHeader()
    1680          70 :          .WriteUInt16( 0x0000 );          // reserved
    1681          70 : }
    1682             : 
    1683          70 : void WMFWriter::UpdateHeader()
    1684             : {
    1685             :     sal_uLong nPos;
    1686             :     sal_uInt32 nFileSize;
    1687             : 
    1688          70 :     nPos=pWMF->Tell();                 // endposition = total size of file
    1689          70 :     nFileSize=nPos-nMetafileHeaderPos; // subtract size of 1st header
    1690          70 :     if ((nFileSize&1)!=0) {            // if needed round to words
    1691           0 :         pWMF->WriteUChar( 0 );
    1692           0 :         nPos++;
    1693           0 :         nFileSize++;
    1694             :     }
    1695          70 :     nFileSize>>=1;                    // convert to number of words
    1696          70 :     pWMF->Seek(nMetafileHeaderPos+6); // to filesize entry in second header
    1697          70 :     pWMF->WriteUInt32( nFileSize );               // rectify file size
    1698          70 :     pWMF->SeekRel(2);                 // to max-recond-length-entry in second header
    1699          70 :     pWMF->WriteUInt32( nMaxRecordSize );          // and rectify
    1700          70 :     pWMF->Seek(nPos);
    1701          70 : }
    1702             : 
    1703          70 : bool WMFWriter::WriteWMF( const GDIMetaFile& rMTF, SvStream& rTargetStream,
    1704             :                             FilterConfigItem* pFConfigItem, bool bPlaceable )
    1705             : {
    1706             :     WMFWriterAttrStackMember * pAt;
    1707             : 
    1708          70 :     bEmbedEMF = true;
    1709          70 :     bStatus=true;
    1710          70 :     pVirDev = new VirtualDevice;
    1711             : 
    1712          70 :     if (pFConfigItem)
    1713             :     {
    1714          70 :         xStatusIndicator = pFConfigItem->GetStatusIndicator();
    1715          70 :         if ( xStatusIndicator.is() )
    1716             :         {
    1717           0 :             OUString aMsg;
    1718           0 :             xStatusIndicator->start( aMsg, 100 );
    1719             :         }
    1720             :     }
    1721          70 :     nLastPercent=0;
    1722             : 
    1723          70 :     pWMF=&rTargetStream;
    1724          70 :     pWMF->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
    1725             : 
    1726          70 :     nMaxRecordSize=0;
    1727             : 
    1728          70 :     aSrcMapMode=rMTF.GetPrefMapMode();
    1729             : 
    1730          70 :     if( bPlaceable )
    1731             :     {
    1732          70 :         aTargetMapMode = aSrcMapMode;
    1733          70 :         aTargetSize = rMTF.GetPrefSize();
    1734          70 :         sal_uInt16 nTargetDivisor = CalcSaveTargetMapMode(aTargetMapMode, aTargetSize);
    1735          70 :         aTargetSize.Width() /= nTargetDivisor;
    1736          70 :         aTargetSize.Height() /= nTargetDivisor;
    1737             :     }
    1738             :     else
    1739             :     {
    1740           0 :         aTargetMapMode = MapMode( MAP_INCH );
    1741             : 
    1742           0 :         const long      nUnit = pVirDev->LogicToPixel( Size( 1, 1 ), aTargetMapMode ).Width();
    1743           0 :         const Fraction  aFrac( 1, nUnit );
    1744             : 
    1745           0 :         aTargetMapMode.SetScaleX( aFrac );
    1746           0 :         aTargetMapMode.SetScaleY( aFrac );
    1747           0 :         aTargetSize = OutputDevice::LogicToLogic( rMTF.GetPrefSize(), aSrcMapMode, aTargetMapMode );
    1748             :     }
    1749             : 
    1750          70 :     pVirDev->SetMapMode( aTargetMapMode );
    1751             : 
    1752          70 :     pAttrStack=NULL;
    1753             : 
    1754        1190 :     for (sal_uInt16 i=0; i<MAXOBJECTHANDLES; i++)
    1755        1120 :         bHandleAllocated[i]=false;
    1756             : 
    1757          70 :     nDstPenHandle=0xffff;
    1758          70 :     nDstFontHandle=0xffff;
    1759          70 :     nDstBrushHandle=0xffff;
    1760             : 
    1761          70 :     nNumberOfActions=0;
    1762          70 :     nNumberOfBitmaps=0;
    1763          70 :     nWrittenActions=0;
    1764          70 :     nWrittenBitmaps=0;
    1765          70 :     nActBitmapPercent=0;
    1766             : 
    1767          70 :     CountActionsAndBitmaps(rMTF);
    1768             : 
    1769          70 :     WriteHeader(rMTF,bPlaceable);
    1770          70 :     if( bEmbedEMF )
    1771          70 :         WriteEmbeddedEMF( rMTF );
    1772          70 :     WMFRecord_SetWindowOrg(Point(0,0));
    1773          70 :     WMFRecord_SetWindowExt(rMTF.GetPrefSize());
    1774          70 :     WMFRecord_SetBkMode( true );
    1775             : 
    1776          70 :     eDstROP2 = eSrcRasterOp = ROP_OVERPAINT;
    1777          70 :     WMFRecord_SetROP2(eDstROP2);
    1778             : 
    1779          70 :     aDstLineInfo = LineInfo();
    1780          70 :     aDstLineColor = aSrcLineColor = Color( COL_BLACK );
    1781          70 :     CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
    1782             : 
    1783          70 :     aDstFillColor = aSrcFillColor = Color( COL_WHITE );
    1784          70 :     CreateSelectDeleteBrush( aDstFillColor );
    1785             : 
    1786          70 :     aDstClipRegion = aSrcClipRegion = vcl::Region();
    1787          70 :     bDstIsClipping = bSrcIsClipping = false;
    1788             : 
    1789          70 :     vcl::Font aFont;
    1790          70 :     aFont.SetCharSet( GetExtendedTextEncoding( RTL_TEXTENCODING_MS_1252 ) );
    1791          70 :     aFont.SetColor( Color( COL_WHITE ) );
    1792          70 :     aFont.SetAlign( ALIGN_BASELINE );
    1793          70 :     aDstFont = aSrcFont = aFont;
    1794          70 :     CreateSelectDeleteFont(aDstFont);
    1795             : 
    1796          70 :     eDstTextAlign = eSrcTextAlign = ALIGN_BASELINE;
    1797          70 :     eDstHorTextAlign = eSrcHorTextAlign = W_TA_LEFT;
    1798          70 :     WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
    1799             : 
    1800          70 :     aDstTextColor = aSrcTextColor = Color( COL_WHITE );
    1801          70 :     WMFRecord_SetTextColor(aDstTextColor);
    1802             : 
    1803             :     // Write records
    1804          70 :     WriteRecords(rMTF);
    1805             : 
    1806          70 :     WMFRecord_EndOfFile();
    1807          70 :     UpdateHeader();
    1808             : 
    1809         140 :     while(pAttrStack)
    1810             :     {
    1811           0 :         pAt=pAttrStack;
    1812           0 :         pAttrStack=pAt->pSucc;
    1813           0 :         delete pAt;
    1814             :     }
    1815             : 
    1816          70 :     delete pVirDev;
    1817             : 
    1818          70 :     if ( xStatusIndicator.is() )
    1819           0 :         xStatusIndicator->end();
    1820             : 
    1821          70 :     return bStatus;
    1822             : }
    1823             : 
    1824          70 : sal_uInt16 WMFWriter::CalcSaveTargetMapMode(MapMode& rMapMode,
    1825             :                                         const Size& rPrefSize)
    1826             : {
    1827          70 :     Fraction    aDivFrac(2, 1);
    1828          70 :     sal_uInt16      nDivisor = 1;
    1829             : 
    1830          70 :     Size aSize = OutputDevice::LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
    1831             : 
    1832         140 :     while( nDivisor <= 64 && (aSize.Width() > 32767 || aSize.Height() > 32767) )
    1833             :     {
    1834           0 :         Fraction aFrac = rMapMode.GetScaleX();
    1835             : 
    1836           0 :         aFrac *= aDivFrac;
    1837           0 :         rMapMode.SetScaleX(aFrac);
    1838           0 :         aFrac = rMapMode.GetScaleY();
    1839           0 :         aFrac *= aDivFrac;
    1840           0 :         rMapMode.SetScaleY(aFrac);
    1841           0 :         nDivisor <<= 1;
    1842           0 :         aSize = OutputDevice::LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
    1843             :     }
    1844             : 
    1845          70 :     return nDivisor;
    1846             : }
    1847             : 
    1848          70 : void WMFWriter::WriteEmbeddedEMF( const GDIMetaFile& rMTF )
    1849             : {
    1850          70 :     SvMemoryStream aStream;
    1851         140 :     EMFWriter aEMFWriter(aStream);
    1852             : 
    1853          70 :     if( aEMFWriter.WriteEMF( rMTF ) )
    1854             :     {
    1855          70 :         sal_Size nTotalSize = aStream.Tell();
    1856          70 :         if( nTotalSize > SAL_MAX_UINT32 )
    1857          70 :             return;
    1858          70 :         aStream.Seek( 0 );
    1859          70 :         sal_uInt32 nRemainingSize = static_cast< sal_uInt32 >( nTotalSize );
    1860          70 :         sal_uInt32 nRecCounts = ( (nTotalSize - 1) / 0x2000 ) + 1;
    1861          70 :         sal_uInt16 nCheckSum = 0, nWord;
    1862             : 
    1863          70 :         sal_uInt32 nPos = 0;
    1864             : 
    1865     2539976 :         while( nPos + 1 < nTotalSize )
    1866             :         {
    1867     2539836 :             aStream.ReadUInt16( nWord );
    1868     2539836 :             nCheckSum ^= nWord;
    1869     2539836 :             nPos += 2;
    1870             :         }
    1871             : 
    1872          70 :         nCheckSum = static_cast< sal_uInt16 >( nCheckSum * -1 );
    1873             : 
    1874          70 :         aStream.Seek( 0 );
    1875         798 :         while( nRemainingSize > 0 )
    1876             :         {
    1877             :             sal_uInt32 nCurSize;
    1878         658 :             if( nRemainingSize > 0x2000 )
    1879             :             {
    1880         588 :                 nCurSize = 0x2000;
    1881         588 :                 nRemainingSize -= 0x2000;
    1882             :             }
    1883             :             else
    1884             :             {
    1885          70 :                 nCurSize = nRemainingSize;
    1886          70 :                 nRemainingSize = 0;
    1887             :             }
    1888             :             WriteEMFRecord( aStream,
    1889             :                             nCurSize,
    1890             :                             nRemainingSize,
    1891             :                             nTotalSize,
    1892             :                             nRecCounts,
    1893         658 :                             nCheckSum );
    1894         658 :             nCheckSum = 0;
    1895             :         }
    1896          70 :     }
    1897             : }
    1898             : 
    1899         658 : void WMFWriter::WriteEMFRecord( SvMemoryStream& rStream, sal_uInt32 nCurSize, sal_uInt32 nRemainingSize,
    1900             :                 sal_uInt32 nTotalSize, sal_uInt32 nRecCounts, sal_uInt16 nCheckSum )
    1901             : {
    1902             :    // according to http://msdn.microsoft.com/en-us/library/dd366152%28PROT.13%29.aspx
    1903         658 :    WriteRecordHeader( 0, W_META_ESCAPE );
    1904         658 :    pWMF->WriteUInt16( W_MFCOMMENT )         // same as META_ESCAPE_ENHANCED_METAFILE
    1905        1316 :          .WriteUInt16( ( nCurSize + 34 ) )  // we will always have a 34 byte escape header:
    1906         658 :          .WriteUInt32( 0x43464D57 )        // WMFC
    1907         658 :          .WriteUInt32( 0x00000001 )        // Comment type
    1908         658 :          .WriteUInt32( 0x00010000 )        // version
    1909        1316 :          .WriteUInt16( nCheckSum )                      // check sum
    1910         658 :          .WriteUInt32( 0 )                 // flags = 0
    1911         658 :          .WriteUInt32( nRecCounts )                     // total number of records
    1912         658 :          .WriteUInt32( nCurSize )                       // size of this record's data
    1913         658 :          .WriteUInt32( nRemainingSize )                 // remaining size of data in following records, missing in MSDN documentation
    1914         658 :          .WriteUInt32( nTotalSize );                    // total size of EMF stream
    1915             : 
    1916         658 :    pWMF->Write( static_cast< const sal_Char* >( rStream.GetData() ) + rStream.Tell(), nCurSize );
    1917         658 :    rStream.SeekRel( nCurSize );
    1918         658 :    UpdateRecordHeader();
    1919        1891 : }
    1920             : 
    1921             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10