LCOV - code coverage report
Current view: top level - vcl/source/filter/wmf - emfwr.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 493 782 63.0 %
Date: 2015-06-13 12:38:46 Functions: 29 34 85.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "sal/config.h"
      21             : 
      22             : #include <algorithm>
      23             : 
      24             : #include "emfwr.hxx"
      25             : #include <rtl/strbuf.hxx>
      26             : #include <tools/helpers.hxx>
      27             : #include <tools/fract.hxx>
      28             : #include <basegfx/polygon/b2dpolygon.hxx>
      29             : #include <basegfx/polygon/b2dpolypolygon.hxx>
      30             : #include <vcl/lineinfo.hxx>
      31             : #include <vcl/dibtools.hxx>
      32             : #include <boost/scoped_array.hpp>
      33             : 
      34             : #define WIN_EMR_POLYGON                     3
      35             : #define WIN_EMR_POLYLINE                    4
      36             : #define WIN_EMR_POLYBEZIERTO                5
      37             : #define WIN_EMR_POLYLINETO                  6
      38             : #define WIN_EMR_POLYPOLYGON                 8
      39             : #define WIN_EMR_SETWINDOWEXTEX              9
      40             : #define WIN_EMR_SETWINDOWORGEX              10
      41             : #define WIN_EMR_SETVIEWPORTEXTEX            11
      42             : #define WIN_EMR_SETVIEWPORTORGEX            12
      43             : #define WIN_EMR_EOF                         14
      44             : #define WIN_EMR_SETPIXELV                   15
      45             : #define WIN_EMR_SETMAPMODE                  17
      46             : #define WIN_EMR_SETBKMODE                   18
      47             : #define WIN_EMR_SETROP2                     20
      48             : #define WIN_EMR_SETTEXTALIGN                22
      49             : #define WIN_EMR_SETTEXTCOLOR                24
      50             : #define WIN_EMR_MOVETOEX                    27
      51             : #define WIN_EMR_INTERSECTCLIPRECT           30
      52             : #define WIN_EMR_SAVEDC                      33
      53             : #define WIN_EMR_RESTOREDC                   34
      54             : #define WIN_EMR_SELECTOBJECT                37
      55             : #define WIN_EMR_CREATEPEN                   38
      56             : #define WIN_EMR_CREATEBRUSHINDIRECT         39
      57             : #define WIN_EMR_DELETEOBJECT                40
      58             : #define WIN_EMR_ELLIPSE                     42
      59             : #define WIN_EMR_RECTANGLE                   43
      60             : #define WIN_EMR_ROUNDRECT                   44
      61             : #define WIN_EMR_LINETO                      54
      62             : #define WIN_EMR_BEGINPATH                   59
      63             : #define WIN_EMR_ENDPATH                     60
      64             : #define WIN_EMR_CLOSEFIGURE                 61
      65             : #define WIN_EMR_FILLPATH                    62
      66             : #define WIN_EMR_STROKEPATH                  64
      67             : 
      68             : #define WIN_EMR_GDICOMMENT                  70
      69             : #define WIN_EMR_STRETCHDIBITS               81
      70             : #define WIN_EMR_EXTCREATEFONTINDIRECTW      82
      71             : #define WIN_EMR_EXTTEXTOUTW                 84
      72             : 
      73             : #define WIN_SRCCOPY                         0x00CC0020L
      74             : #define WIN_SRCPAINT                        0x00EE0086L
      75             : #define WIN_SRCAND                          0x008800C6L
      76             : #define WIN_SRCINVERT                       0x00660046L
      77             : #define WIN_EMR_COMMENT_EMFPLUS             0x2B464D45L
      78             : 
      79             : #define HANDLE_INVALID                      0xffffffff
      80             : #define MAXHANDLES                          65000
      81             : 
      82             : #define LINE_SELECT                         0x00000001
      83             : #define FILL_SELECT                         0x00000002
      84             : #define TEXT_SELECT                         0x00000004
      85             : 
      86             : /* Text Alignment Options */
      87             : #define TA_RIGHT                            2
      88             : 
      89             : #define TA_TOP                              0
      90             : #define TA_BOTTOM                           8
      91             : #define TA_BASELINE                         24
      92             : #define TA_RTLREADING                       256
      93             : 
      94             : #define MM_ANISOTROPIC                      8
      95             : 
      96             : typedef enum
      97             : {
      98             :   EmfPlusHeader                     = 0x4001,
      99             :   EmfPlusEndOfFile                  = 0x4002,
     100             :   EmfPlusComment                    = 0x4003,
     101             :   EmfPlusGetDC                      = 0x4004,
     102             :   EmfPlusMultiFormatStart           = 0x4005,
     103             :   EmfPlusMultiFormatSection         = 0x4006,
     104             :   EmfPlusMultiFormatEnd             = 0x4007,
     105             :   EmfPlusObject                     = 0x4008,
     106             :   EmfPlusClear                      = 0x4009,
     107             :   EmfPlusFillRects                  = 0x400A,
     108             :   EmfPlusDrawRects                  = 0x400B,
     109             :   EmfPlusFillPolygon                = 0x400C,
     110             :   EmfPlusDrawLines                  = 0x400D,
     111             :   EmfPlusFillEllipse                = 0x400E,
     112             :   EmfPlusDrawEllipse                = 0x400F,
     113             :   EmfPlusFillPie                    = 0x4010,
     114             :   EmfPlusDrawPie                    = 0x4011,
     115             :   EmfPlusDrawArc                    = 0x4012,
     116             :   EmfPlusFillRegion                 = 0x4013,
     117             :   EmfPlusFillPath                   = 0x4014,
     118             :   EmfPlusDrawPath                   = 0x4015,
     119             :   EmfPlusFillClosedCurve            = 0x4016,
     120             :   EmfPlusDrawClosedCurve            = 0x4017,
     121             :   EmfPlusDrawCurve                  = 0x4018,
     122             :   EmfPlusDrawBeziers                = 0x4019,
     123             :   EmfPlusDrawImage                  = 0x401A,
     124             :   EmfPlusDrawImagePoints            = 0x401B,
     125             :   EmfPlusDrawstring                 = 0x401C,
     126             :   EmfPlusSetRenderingOrigin         = 0x401D,
     127             :   EmfPlusSetAntiAliasMode           = 0x401E,
     128             :   EmfPlusSetTextRenderingHint       = 0x401F,
     129             :   EmfPlusSetTextContrast            = 0x4020,
     130             :   EmfPlusSetInterpolationMode       = 0x4021,
     131             :   EmfPlusSetPixelOffsetMode         = 0x4022,
     132             :   EmfPlusSetCompositingMode         = 0x4023,
     133             :   EmfPlusSetCompositingQuality      = 0x4024,
     134             :   EmfPlusSave                       = 0x4025,
     135             :   EmfPlusRestore                    = 0x4026,
     136             :   EmfPlusBeginContainer             = 0x4027,
     137             :   EmfPlusBeginContainerNoParams     = 0x4028,
     138             :   EmfPlusEndContainer               = 0x4029,
     139             :   EmfPlusSetWorldTransform          = 0x402A,
     140             :   EmfPlusResetWorldTransform        = 0x402B,
     141             :   EmfPlusMultiplyWorldTransform     = 0x402C,
     142             :   EmfPlusTranslateWorldTransform    = 0x402D,
     143             :   EmfPlusScaleWorldTransform        = 0x402E,
     144             :   EmfPlusRotateWorldTransform       = 0x402F,
     145             :   EmfPlusSetPageTransform           = 0x4030,
     146             :   EmfPlusResetClip                  = 0x4031,
     147             :   EmfPlusSetClipRect                = 0x4032,
     148             :   EmfPlusSetClipPath                = 0x4033,
     149             :   EmfPlusSetClipRegion              = 0x4034,
     150             :   EmfPlusOffsetClip                 = 0x4035,
     151             :   EmfPlusDrawDriverstring           = 0x4036,
     152             :   EmfPlusStrokeFillPath             = 0x4037,
     153             :   EmfPlusSerializableObject         = 0x4038,
     154             :   EmfPlusSetTSGraphics              = 0x4039,
     155             :   EmfPlusSetTSClip                  = 0x403A
     156             : } EmfPlusRecordType;
     157             : 
     158         297 : void EMFWriter::ImplBeginCommentRecord( sal_Int32 nCommentType )
     159             : {
     160         297 :     ImplBeginRecord( WIN_EMR_GDICOMMENT );
     161         297 :     m_rStm.SeekRel( 4 );
     162         297 :     m_rStm.WriteInt32( nCommentType );
     163         297 : }
     164             : 
     165         297 : void EMFWriter::ImplEndCommentRecord()
     166             : {
     167         297 :     if( mbRecordOpen )
     168             :     {
     169         297 :         sal_Int32 nActPos = m_rStm.Tell();
     170         297 :         m_rStm.Seek( mnRecordPos + 8 );
     171         297 :         m_rStm.WriteUInt32( nActPos - mnRecordPos - 0xc );
     172         297 :         m_rStm.Seek( nActPos );
     173             :     }
     174         297 :     ImplEndRecord();
     175         297 : }
     176             : 
     177         553 : void EMFWriter::ImplBeginPlusRecord( sal_uInt16 nType, sal_uInt16 nFlags )
     178             : {
     179             :     DBG_ASSERT( !mbRecordPlusOpen, "Another EMF+ record is already opened!" );
     180             : 
     181         553 :     if( !mbRecordPlusOpen )
     182             :     {
     183         553 :         mbRecordPlusOpen = true;
     184         553 :         mnRecordPlusPos = m_rStm.Tell();
     185             : 
     186         553 :         m_rStm.WriteUInt16( nType ).WriteUInt16( nFlags );
     187         553 :         m_rStm.SeekRel( 8 );
     188             :     }
     189         553 : }
     190             : 
     191         553 : void EMFWriter::ImplEndPlusRecord()
     192             : {
     193             :     DBG_ASSERT( mbRecordPlusOpen, "EMF+ Record was not opened!" );
     194             : 
     195         553 :     if( mbRecordPlusOpen )
     196             :     {
     197         553 :         sal_Int32 nActPos = m_rStm.Tell();
     198         553 :         sal_Int32 nSize = nActPos - mnRecordPlusPos;
     199         553 :         m_rStm.Seek( mnRecordPlusPos + 4 );
     200         553 :         m_rStm.WriteUInt32( nSize )         // Size
     201        1106 :               .WriteUInt32( nSize - 0xc ); // Data Size
     202         553 :         m_rStm.Seek( nActPos );
     203         553 :         mbRecordPlusOpen = false;
     204             :     }
     205         553 : }
     206             : 
     207         553 : void EMFWriter::ImplPlusRecord( sal_uInt16 nType, sal_uInt16 nFlags )
     208             : {
     209         553 :     ImplBeginPlusRecord( nType, nFlags );
     210         553 :     ImplEndPlusRecord();
     211         553 : }
     212             : 
     213          79 : void EMFWriter::WriteEMFPlusHeader( const Size &rMtfSizePix, const Size &rMtfSizeLog )
     214             : {
     215          79 :     ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS );
     216             : 
     217          79 :     sal_Int32 nDPIX = rMtfSizePix.Width()*25;
     218          79 :     sal_Int32 nDivX = rMtfSizeLog.Width()/100;
     219          79 :     if (nDivX)
     220          79 :         nDPIX /= nDivX;    // DPI X
     221             : 
     222          79 :     sal_Int32 nDPIY = rMtfSizePix.Height()*25;
     223          79 :     sal_Int32 nDivY = rMtfSizeLog.Height()/100;
     224          79 :     if (nDivY)
     225          79 :         nDPIY /= nDivY; // DPI Y
     226             : 
     227          79 :     m_rStm.WriteInt16( EmfPlusHeader );
     228          79 :     m_rStm.WriteInt16( 0x01 )  // Flags - Dual Mode // TODO: Check this
     229          79 :           .WriteInt32( 0x1C )  // Size
     230          79 :           .WriteInt32( 0x10 )  // Data Size
     231          79 :           .WriteInt32( 0xdbc01002 ) // (lower 12bits) 1-> v1 2-> v1.1 // TODO: Check this
     232          79 :           .WriteInt32( 0x01 ) // Video display
     233          79 :           .WriteInt32( nDPIX )
     234          79 :           .WriteInt32( nDPIY );
     235          79 :     ImplEndCommentRecord();
     236             : 
     237             :     // Write more properties
     238          79 :     ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS );
     239          79 :     ImplPlusRecord( EmfPlusSetPixelOffsetMode, 0x0 );
     240          79 :     ImplPlusRecord( EmfPlusSetAntiAliasMode, 0x09 );      // TODO: Check actual values for AntiAlias
     241          79 :     ImplPlusRecord( EmfPlusSetCompositingQuality, 0x0100 ); // Default Quality
     242          79 :     ImplPlusRecord( EmfPlusSetPageTransform, 1 );
     243          79 :     ImplPlusRecord( EmfPlusSetInterpolationMode, 0x00 );  // Default
     244          79 :     ImplPlusRecord( EmfPlusGetDC, 0x00 );
     245          79 :     ImplEndCommentRecord();
     246          79 : }
     247             : 
     248          79 : void EMFWriter::ImplWritePlusEOF()
     249             : {
     250          79 :     ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS );
     251          79 :     ImplPlusRecord( EmfPlusEndOfFile, 0x0 );
     252          79 :     ImplEndCommentRecord();
     253          79 : }
     254             : 
     255           0 : void EMFWriter::ImplWritePlusColor( const Color& rColor, const sal_uInt32& nTrans )
     256             : {
     257           0 :     sal_uInt32 nAlpha = ((100-nTrans)*0xFF)/100;
     258           0 :     sal_uInt32 nCol = rColor.GetBlue();
     259             : 
     260           0 :     nCol |= ( (sal_uInt32) rColor.GetGreen() ) << 8;
     261           0 :     nCol |= ( (sal_uInt32) rColor.GetRed() ) << 16;
     262           0 :     nCol |= ( nAlpha << 24 );
     263           0 :     m_rStm.WriteUInt32( nCol );
     264           0 : }
     265             : 
     266           0 : void EMFWriter::ImplWritePlusPoint( const Point& rPoint )
     267             : {
     268             :     // Convert to pixels
     269           0 :     const Point aPoint(maVDev->LogicToPixel( rPoint, maDestMapMode ));
     270           0 :     m_rStm.WriteUInt16( aPoint.X() ).WriteUInt16( aPoint.Y() );
     271           0 : }
     272             : 
     273           0 : void EMFWriter::ImplWritePlusFillPolygonRecord( const Polygon& rPoly, const sal_uInt32& nTrans )
     274             : {
     275           0 :     ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS );
     276           0 :     if( rPoly.GetSize() )
     277             :     {
     278           0 :         ImplBeginPlusRecord( EmfPlusFillPolygon, 0xC000 ); // Sets the color as well
     279           0 :         ImplWritePlusColor( maVDev->GetFillColor(), nTrans );
     280           0 :         m_rStm.WriteUInt32( rPoly.GetSize() );
     281           0 :         for( sal_uInt16 i = 0; i < rPoly.GetSize(); i++ )
     282           0 :             ImplWritePlusPoint( rPoly[ i ] );
     283           0 :         ImplEndPlusRecord();
     284             :     }
     285           0 :     ImplEndCommentRecord();
     286           0 : }
     287             : 
     288          79 : bool EMFWriter::WriteEMF(const GDIMetaFile& rMtf)
     289             : {
     290          79 :     const sal_uLong nHeaderPos = m_rStm.Tell();
     291             : 
     292          79 :     maVDev->EnableOutput( false );
     293          79 :     maVDev->SetMapMode( rMtf.GetPrefMapMode() );
     294             :     // don't work with pixel as destination map mode -> higher resolution preferrable
     295          79 :     maDestMapMode.SetMapUnit( MAP_100TH_MM );
     296          79 :     mpHandlesUsed = new bool[ MAXHANDLES ];
     297          79 :     memset( mpHandlesUsed, 0, MAXHANDLES * sizeof( bool ) );
     298          79 :     mnHandleCount = mnRecordCount = mnRecordPos = mnRecordPlusPos = 0;
     299          79 :     mbRecordOpen = mbRecordPlusOpen = false;
     300          79 :     mbLineChanged = mbFillChanged = mbTextChanged = false;
     301          79 :     mnLineHandle = mnFillHandle = mnTextHandle = HANDLE_INVALID;
     302          79 :     mnHorTextAlign = 0;
     303             : 
     304          79 :     const Size aMtfSizePix( maVDev->LogicToPixel( rMtf.GetPrefSize(), rMtf.GetPrefMapMode() ) );
     305          79 :     const Size aMtfSizeLog( OutputDevice::LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_100TH_MM ) );
     306             : 
     307             :     // seek over header
     308             :     // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits()
     309          79 :     m_rStm.SeekRel( 108 );
     310             : 
     311             :     // Write EMF+ Header
     312          79 :     WriteEMFPlusHeader( aMtfSizePix, aMtfSizeLog );
     313             : 
     314             :     // write initial values
     315             : 
     316             :     // set 100th mm map mode in EMF
     317          79 :     ImplBeginRecord( WIN_EMR_SETMAPMODE );
     318          79 :     m_rStm.WriteInt32( MM_ANISOTROPIC );
     319          79 :     ImplEndRecord();
     320             : 
     321          79 :     ImplBeginRecord( WIN_EMR_SETVIEWPORTEXTEX );
     322          79 :     m_rStm.WriteInt32( maVDev->GetDPIX() ).WriteInt32( maVDev->GetDPIY() );
     323          79 :     ImplEndRecord();
     324             : 
     325          79 :     ImplBeginRecord( WIN_EMR_SETWINDOWEXTEX );
     326          79 :     m_rStm.WriteInt32( 2540 ).WriteInt32( 2540 );
     327          79 :     ImplEndRecord();
     328             : 
     329          79 :     ImplBeginRecord( WIN_EMR_SETVIEWPORTORGEX );
     330          79 :     m_rStm.WriteInt32( 0 ).WriteInt32( 0 );
     331          79 :     ImplEndRecord();
     332             : 
     333          79 :     ImplBeginRecord( WIN_EMR_SETWINDOWORGEX );
     334          79 :     m_rStm.WriteInt32( 0 ).WriteInt32( 0 );
     335          79 :     ImplEndRecord();
     336             : 
     337          79 :     ImplWriteRasterOp( ROP_OVERPAINT );
     338             : 
     339          79 :     ImplBeginRecord( WIN_EMR_SETBKMODE );
     340          79 :     m_rStm.WriteUInt32( 1 ); // TRANSPARENT
     341          79 :     ImplEndRecord();
     342             : 
     343             :     // write emf data
     344          79 :     ImplWrite( rMtf );
     345             : 
     346          79 :     ImplWritePlusEOF();
     347             : 
     348          79 :     ImplBeginRecord( WIN_EMR_EOF );
     349          79 :     m_rStm.WriteUInt32( 0 )      // nPalEntries
     350          79 :           .WriteUInt32( 0x10 )     // offPalEntries
     351          79 :           .WriteUInt32( 0x14 );    // nSizeLast
     352          79 :     ImplEndRecord();
     353             : 
     354             :     // write header
     355          79 :     const sal_uLong nEndPos = m_rStm.Tell(); m_rStm.Seek( nHeaderPos );
     356             : 
     357          79 :     m_rStm.WriteUInt32( 0x00000001 ).WriteUInt32( 108 )   //use [MS-EMF 2.2.11] HeaderExtension2 Object
     358         158 :             .WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aMtfSizePix.Width() - 1 ).WriteInt32( aMtfSizePix.Height() - 1 )
     359         158 :             .WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aMtfSizeLog.Width() - 1 ).WriteInt32( aMtfSizeLog.Height() - 1 )
     360         158 :             .WriteUInt32( 0x464d4520 ).WriteUInt32( 0x10000 ).WriteUInt32( nEndPos - nHeaderPos )
     361         158 :             .WriteUInt32( mnRecordCount ).WriteUInt16( mnHandleCount + 1 ).WriteUInt16( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
     362         158 :             .WriteInt32( aMtfSizePix.Width() ).WriteInt32( aMtfSizePix.Height() )
     363         158 :             .WriteInt32( aMtfSizeLog.Width() / 100 ).WriteInt32( aMtfSizeLog.Height() / 100 )
     364          79 :             .WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
     365         158 :             .WriteInt32( aMtfSizeLog.Width() * 10 ).WriteInt32( aMtfSizeLog.Height() * 10 ); //use [MS-EMF 2.2.11] HeaderExtension2 Object
     366             : 
     367          79 :     m_rStm.Seek( nEndPos );
     368          79 :     delete[] mpHandlesUsed;
     369             : 
     370          79 :     return( m_rStm.GetError() == ERRCODE_NONE );
     371             : }
     372             : 
     373        1521 : sal_uLong EMFWriter::ImplAcquireHandle()
     374             : {
     375        1521 :     sal_uLong nHandle = HANDLE_INVALID;
     376             : 
     377        3502 :     for( sal_uLong i = 0; i < MAXHANDLES && ( HANDLE_INVALID == nHandle ); i++ )
     378             :     {
     379        1981 :         if( !mpHandlesUsed[ i ] )
     380             :         {
     381        1521 :             mpHandlesUsed[ i ] = true;
     382             : 
     383        1521 :             if( ( nHandle = i ) == mnHandleCount )
     384         111 :                 mnHandleCount++;
     385             :         }
     386             :     }
     387             : 
     388             :     DBG_ASSERT( nHandle != HANDLE_INVALID, "No more handles available" );
     389        1521 :     return( nHandle != HANDLE_INVALID ? nHandle + 1 : HANDLE_INVALID );
     390             : }
     391             : 
     392        1410 : void EMFWriter::ImplReleaseHandle( sal_uLong nHandle )
     393             : {
     394             :     DBG_ASSERT( nHandle && ( nHandle < MAXHANDLES ), "Handle out of range" );
     395        1410 :     mpHandlesUsed[ nHandle - 1 ] = false;
     396        1410 : }
     397             : 
     398       12580 : void EMFWriter::ImplBeginRecord( sal_uInt32 nType )
     399             : {
     400             :     DBG_ASSERT( !mbRecordOpen, "Another record is already opened!" );
     401             : 
     402       12580 :     if( !mbRecordOpen )
     403             :     {
     404       12580 :         mbRecordOpen = true;
     405       12580 :         mnRecordPos = m_rStm.Tell();
     406             : 
     407       12580 :         m_rStm.WriteUInt32( nType );
     408       12580 :         m_rStm.SeekRel( 4 );
     409             :     }
     410       12580 : }
     411             : 
     412       12580 : void EMFWriter::ImplEndRecord()
     413             : {
     414             :     DBG_ASSERT( mbRecordOpen, "Record was not opened!" );
     415             : 
     416       12580 :     if( mbRecordOpen )
     417             :     {
     418       12580 :         sal_Int32 nFillBytes, nActPos = m_rStm.Tell();
     419       12580 :         m_rStm.Seek( mnRecordPos + 4 );
     420       12580 :         nFillBytes = nActPos - mnRecordPos;
     421       12580 :         nFillBytes += 3;    // each record has to be dword aligned
     422       12580 :         nFillBytes ^= 3;
     423       12580 :         nFillBytes &= 3;
     424       12580 :         m_rStm.WriteUInt32( ( nActPos - mnRecordPos ) + nFillBytes );
     425       12580 :         m_rStm.Seek( nActPos );
     426       25164 :         while( nFillBytes-- )
     427           4 :             m_rStm.WriteUChar( 0 );
     428       12580 :         mnRecordCount++;
     429       12580 :         mbRecordOpen = false;
     430             :     }
     431       12580 : }
     432             : 
     433        1521 : bool EMFWriter::ImplPrepareHandleSelect( sal_uInt32& rHandle, sal_uLong nSelectType )
     434             : {
     435        1521 :     if( rHandle != HANDLE_INVALID )
     436             :     {
     437        1410 :         sal_uInt32 nStockObject = 0x80000000;
     438             : 
     439        1410 :         if( LINE_SELECT == nSelectType )
     440         941 :             nStockObject |= 0x00000007;
     441         469 :         else if( FILL_SELECT == nSelectType )
     442         118 :             nStockObject |= 0x00000001;
     443         351 :         else if( TEXT_SELECT == nSelectType )
     444         351 :             nStockObject |= 0x0000000a;
     445             : 
     446             :         // select stock object first
     447        1410 :         ImplBeginRecord( WIN_EMR_SELECTOBJECT );
     448        1410 :         m_rStm.WriteUInt32( nStockObject );
     449        1410 :         ImplEndRecord();
     450             : 
     451             :         // destroy handle of created object
     452        1410 :         ImplBeginRecord( WIN_EMR_DELETEOBJECT );
     453        1410 :         m_rStm.WriteUInt32( rHandle );
     454        1410 :         ImplEndRecord();
     455             : 
     456             :         // mark handle as free
     457        1410 :         ImplReleaseHandle( rHandle );
     458             :     }
     459             : 
     460        1521 :     rHandle = ImplAcquireHandle();
     461             : 
     462        1521 :     return( HANDLE_INVALID != rHandle );
     463             : }
     464             : 
     465         977 : void EMFWriter::ImplCheckLineAttr()
     466             : {
     467         977 :     if( mbLineChanged && ImplPrepareHandleSelect( mnLineHandle, LINE_SELECT ) )
     468             :     {
     469         977 :         sal_uInt32 nStyle = maVDev->IsLineColor() ? 0 : 5;
     470         977 :         sal_uInt32 nWidth = 0, nHeight = 0;
     471             : 
     472         977 :         ImplBeginRecord( WIN_EMR_CREATEPEN );
     473         977 :         m_rStm.WriteUInt32( mnLineHandle ).WriteUInt32( nStyle ).WriteUInt32( nWidth ).WriteUInt32( nHeight );
     474         977 :         ImplWriteColor( maVDev->GetLineColor() );
     475         977 :         ImplEndRecord();
     476             : 
     477         977 :         ImplBeginRecord( WIN_EMR_SELECTOBJECT );
     478         977 :         m_rStm.WriteUInt32( mnLineHandle );
     479         977 :         ImplEndRecord();
     480             :     }
     481         977 : }
     482             : 
     483         140 : void EMFWriter::ImplCheckFillAttr()
     484             : {
     485         140 :     if( mbFillChanged && ImplPrepareHandleSelect( mnFillHandle, FILL_SELECT ) )
     486             :     {
     487         140 :         sal_uInt32 nStyle = maVDev->IsFillColor() ? 0 : 1;
     488         140 :         sal_uInt32 nPatternStyle = 0;
     489             : 
     490         140 :         ImplBeginRecord( WIN_EMR_CREATEBRUSHINDIRECT );
     491         140 :         m_rStm.WriteUInt32( mnFillHandle ).WriteUInt32( nStyle );
     492         140 :         ImplWriteColor( maVDev->GetFillColor() );
     493         140 :         m_rStm.WriteUInt32( nPatternStyle );
     494         140 :         ImplEndRecord();
     495             : 
     496         140 :         ImplBeginRecord( WIN_EMR_SELECTOBJECT );
     497         140 :         m_rStm.WriteUInt32( mnFillHandle );
     498         140 :         ImplEndRecord();
     499             :     }
     500         140 : }
     501             : 
     502         404 : void EMFWriter::ImplCheckTextAttr()
     503             : {
     504         404 :     if( mbTextChanged && ImplPrepareHandleSelect( mnTextHandle, TEXT_SELECT ) )
     505             :     {
     506         404 :         const vcl::Font& rFont = maVDev->GetFont();
     507         404 :         OUString         aFontName( rFont.GetName() );
     508             :         sal_Int32        nWeight;
     509             :         sal_uInt16       i;
     510             :         sal_uInt8        nPitchAndFamily;
     511             : 
     512         404 :         ImplBeginRecord( WIN_EMR_EXTCREATEFONTINDIRECTW );
     513         404 :         m_rStm.WriteUInt32( mnTextHandle );
     514         404 :         ImplWriteExtent( -rFont.GetSize().Height() );
     515         404 :         ImplWriteExtent( rFont.GetSize().Width() );
     516         404 :         m_rStm.WriteInt32( rFont.GetOrientation() ).WriteInt32( rFont.GetOrientation() );
     517             : 
     518         404 :         switch( rFont.GetWeight() )
     519             :         {
     520           0 :             case WEIGHT_THIN:       nWeight = 100; break;
     521           0 :             case WEIGHT_ULTRALIGHT: nWeight = 200; break;
     522           0 :             case WEIGHT_LIGHT:      nWeight = 300; break;
     523           0 :             case WEIGHT_SEMILIGHT:  nWeight = 300; break;
     524         389 :             case WEIGHT_NORMAL:     nWeight = 400; break;
     525           0 :             case WEIGHT_MEDIUM:     nWeight = 500; break;
     526           0 :             case WEIGHT_SEMIBOLD:   nWeight = 600; break;
     527          15 :             case WEIGHT_BOLD:       nWeight = 700; break;
     528           0 :             case WEIGHT_ULTRABOLD:  nWeight = 800; break;
     529           0 :             case WEIGHT_BLACK:      nWeight = 900; break;
     530           0 :             default:                nWeight = 0; break;
     531             :         }
     532             : 
     533         404 :         m_rStm.WriteInt32( nWeight );
     534         404 :         m_rStm.WriteUChar( ( ITALIC_NONE == rFont.GetItalic() ) ? 0 : 1 );
     535         404 :         m_rStm.WriteUChar( ( UNDERLINE_NONE == rFont.GetUnderline() ) ? 0 : 1 );
     536         404 :         m_rStm.WriteUChar( ( STRIKEOUT_NONE == rFont.GetStrikeout() ) ? 0 : 1 );
     537         404 :         m_rStm.WriteUChar( ( RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet() ) ? 2 : 0 );
     538         404 :         m_rStm.WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
     539             : 
     540         404 :         switch( rFont.GetPitch() )
     541             :         {
     542           0 :             case PITCH_FIXED:    nPitchAndFamily = 0x01; break;
     543          60 :             case PITCH_VARIABLE: nPitchAndFamily = 0x02; break;
     544         344 :             default:             nPitchAndFamily = 0x00; break;
     545             :         }
     546             : 
     547         404 :         switch( rFont.GetFamily() )
     548             :         {
     549           0 :             case FAMILY_DECORATIVE: nPitchAndFamily |= 0x50; break;
     550           0 :             case FAMILY_MODERN:     nPitchAndFamily |= 0x30; break;
     551         232 :             case FAMILY_ROMAN:      nPitchAndFamily |= 0x10; break;
     552           0 :             case FAMILY_SCRIPT:     nPitchAndFamily |= 0x40; break;
     553          48 :             case FAMILY_SWISS:      nPitchAndFamily |= 0x20; break;
     554         124 :             default: break;
     555             :         }
     556             : 
     557         404 :         m_rStm.WriteUChar( nPitchAndFamily );
     558             : 
     559       13332 :         for( i = 0; i < 32; i++ )
     560       12928 :             m_rStm.WriteUInt16( ( i < aFontName.getLength() ) ? aFontName[ i ] : 0 );
     561             : 
     562             :         // dummy elfFullName
     563       26260 :         for( i = 0; i < 64; i++ )
     564       25856 :             m_rStm.WriteUInt16( 0 );
     565             : 
     566             :         // dummy elfStyle
     567       13332 :         for( i = 0; i < 32; i++ )
     568       12928 :             m_rStm.WriteUInt16( 0 );
     569             : 
     570             :         // dummy elfVersion, elfStyleSize, elfMatch, elfReserved
     571         404 :         m_rStm.WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ) ;
     572             : 
     573             :         // dummy elfVendorId
     574         404 :         m_rStm.WriteUInt32( 0 );
     575             : 
     576             :         // dummy elfCulture
     577         404 :         m_rStm.WriteUInt32( 0 );
     578             : 
     579             :         // dummy elfPanose
     580         404 :         m_rStm.WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
     581             : 
     582             :         // fill record to get a record size divideable by 4
     583         404 :         m_rStm.WriteUInt16( 0 );
     584             : 
     585         404 :         ImplEndRecord();
     586             : 
     587             :         // TextAlign
     588             :         sal_uInt32 nTextAlign;
     589             : 
     590         404 :         switch( rFont.GetAlign() )
     591             :         {
     592          35 :             case ALIGN_TOP:    nTextAlign = TA_TOP; break;
     593           0 :             case ALIGN_BOTTOM: nTextAlign = TA_BOTTOM; break;
     594         369 :             default:           nTextAlign = TA_BASELINE; break;
     595             :         }
     596         404 :         nTextAlign |= mnHorTextAlign;
     597             : 
     598         404 :         ImplBeginRecord( WIN_EMR_SETTEXTALIGN );
     599         404 :         m_rStm.WriteUInt32( nTextAlign );
     600         404 :         ImplEndRecord();
     601             : 
     602             :         // Text color
     603         404 :         ImplBeginRecord( WIN_EMR_SETTEXTCOLOR );
     604         404 :         ImplWriteColor( maVDev->GetTextColor() );
     605         404 :         ImplEndRecord();
     606             : 
     607         404 :         ImplBeginRecord( WIN_EMR_SELECTOBJECT );
     608         404 :         m_rStm.WriteUInt32( mnTextHandle );
     609         404 :         ImplEndRecord();
     610             :     }
     611         404 : }
     612             : 
     613        2340 : void EMFWriter::ImplWriteColor( const Color& rColor )
     614             : {
     615        2340 :     sal_uInt32 nCol = rColor.GetRed();
     616             : 
     617        2340 :     nCol |= ( (sal_uInt32) rColor.GetGreen() ) << 8;
     618        2340 :     nCol |= ( (sal_uInt32) rColor.GetBlue() ) << 16;
     619             : 
     620        2340 :     m_rStm.WriteUInt32( nCol );
     621        2340 : }
     622             : 
     623         920 : void EMFWriter::ImplWriteRasterOp( RasterOp eRop )
     624             : {
     625             :     sal_uInt32 nROP2;
     626             : 
     627         920 :     switch( eRop )
     628             :     {
     629           0 :         case ROP_INVERT: nROP2 = 6; break;
     630           0 :         case ROP_XOR:    nROP2 = 7; break;
     631         920 :         default:         nROP2 = 13;break;
     632             :     }
     633             : 
     634         920 :     ImplBeginRecord( WIN_EMR_SETROP2 );
     635         920 :     m_rStm.WriteUInt32( nROP2 );
     636         920 :     ImplEndRecord();
     637         920 : }
     638             : 
     639        1438 : void EMFWriter::ImplWriteExtent( long nExtent )
     640             : {
     641        1438 :     nExtent = OutputDevice::LogicToLogic( Size( nExtent, 0 ), maVDev->GetMapMode(), maDestMapMode ).Width();
     642        1438 :     m_rStm.WriteInt32( nExtent );
     643        1438 : }
     644             : 
     645        2973 : void EMFWriter::ImplWritePoint( const Point& rPoint )
     646             : {
     647        2973 :     const Point aPoint( OutputDevice::LogicToLogic( rPoint, maVDev->GetMapMode(), maDestMapMode ));
     648        2973 :      m_rStm.WriteInt32( aPoint.X() ).WriteInt32( aPoint.Y() );
     649        2973 : }
     650             : 
     651          28 : void EMFWriter::ImplWriteSize( const Size& rSize)
     652             : {
     653          28 :     const Size aSize( OutputDevice::LogicToLogic( rSize, maVDev->GetMapMode(), maDestMapMode ));
     654          28 :      m_rStm.WriteInt32( aSize.Width() ).WriteInt32( aSize.Height() );
     655          28 : }
     656             : 
     657         635 : void EMFWriter::ImplWriteRect( const Rectangle& rRect )
     658             : {
     659         635 :     const Rectangle aRect( OutputDevice::LogicToLogic ( rRect, maVDev->GetMapMode(), maDestMapMode ));
     660             :     m_rStm
     661         635 :        .WriteInt32( aRect.Left() )
     662        1270 :        .WriteInt32( aRect.Top() )
     663        1270 :        .WriteInt32( aRect.Right() )
     664        1270 :        .WriteInt32( aRect.Bottom() );
     665         635 : }
     666             : 
     667          30 : void EMFWriter::ImplWritePolygonRecord( const Polygon& rPoly, bool bClose )
     668             : {
     669          30 :     if( rPoly.GetSize() )
     670             :     {
     671          30 :         if( rPoly.HasFlags() )
     672           0 :             ImplWritePath( rPoly, bClose );
     673             :         else
     674             :         {
     675          30 :             if( bClose )
     676          12 :                 ImplCheckFillAttr();
     677             : 
     678          30 :             ImplCheckLineAttr();
     679             : 
     680          30 :             ImplBeginRecord( bClose ? WIN_EMR_POLYGON : WIN_EMR_POLYLINE );
     681          30 :             ImplWriteRect( rPoly.GetBoundRect() );
     682          30 :             m_rStm.WriteUInt32( rPoly.GetSize() );
     683             : 
     684         114 :             for( sal_uInt16 i = 0; i < rPoly.GetSize(); i++ )
     685          84 :                 ImplWritePoint( rPoly[ i ] );
     686             : 
     687          30 :             ImplEndRecord();
     688             :         }
     689             :     }
     690          30 : }
     691             : 
     692          12 : void EMFWriter::ImplWritePolyPolygonRecord( const tools::PolyPolygon& rPolyPoly )
     693             : {
     694          12 :     sal_uInt16 n, i, nPolyCount = rPolyPoly.Count();
     695             : 
     696          12 :     if( nPolyCount )
     697             :     {
     698          12 :         if( 1 == nPolyCount )
     699          12 :             ImplWritePolygonRecord( rPolyPoly[ 0 ], true );
     700             :         else
     701             :         {
     702           0 :             bool    bHasFlags = false;
     703           0 :             sal_uInt32  nTotalPoints = 0;
     704             : 
     705           0 :             for( i = 0; i < nPolyCount; i++ )
     706             :             {
     707           0 :                 nTotalPoints += rPolyPoly[ i ].GetSize();
     708           0 :                 if ( rPolyPoly[ i ].HasFlags() )
     709           0 :                     bHasFlags = true;
     710             :             }
     711           0 :             if( nTotalPoints )
     712             :             {
     713           0 :                 if ( bHasFlags )
     714           0 :                     ImplWritePath( rPolyPoly, true );
     715             :                 else
     716             :                 {
     717           0 :                     ImplCheckFillAttr();
     718           0 :                     ImplCheckLineAttr();
     719             : 
     720           0 :                     ImplBeginRecord( WIN_EMR_POLYPOLYGON );
     721           0 :                     ImplWriteRect( rPolyPoly.GetBoundRect() );
     722           0 :                     m_rStm.WriteUInt32( nPolyCount ).WriteUInt32( nTotalPoints );
     723             : 
     724           0 :                     for( i = 0; i < nPolyCount; i++ )
     725           0 :                         m_rStm.WriteUInt32( rPolyPoly[ i ].GetSize() );
     726             : 
     727           0 :                     for( i = 0; i < nPolyCount; i++ )
     728             :                     {
     729           0 :                         const Polygon& rPoly = rPolyPoly[ i ];
     730             : 
     731           0 :                         for( n = 0; n < rPoly.GetSize(); n++ )
     732           0 :                             ImplWritePoint( rPoly[ n ] );
     733             :                     }
     734           0 :                     ImplEndRecord();
     735             :                 }
     736             :             }
     737             :         }
     738             :     }
     739          12 : }
     740             : 
     741           0 : void EMFWriter::ImplWritePath( const tools::PolyPolygon& rPolyPoly, bool bClosed )
     742             : {
     743           0 :     if ( bClosed )
     744           0 :         ImplCheckFillAttr();
     745           0 :     ImplCheckLineAttr();
     746             : 
     747           0 :     ImplBeginRecord( WIN_EMR_BEGINPATH );
     748           0 :     ImplEndRecord();
     749             : 
     750           0 :     sal_uInt16 i, n, o, nPolyCount = rPolyPoly.Count();
     751           0 :     for ( i = 0; i < nPolyCount; i++ )
     752             :     {
     753           0 :         n = 0;
     754           0 :         const Polygon& rPoly = rPolyPoly[ i ];
     755           0 :         while ( n < rPoly.GetSize() )
     756             :         {
     757           0 :             if( n == 0 )
     758             :             {
     759           0 :                 ImplBeginRecord( WIN_EMR_MOVETOEX );
     760           0 :                 ImplWritePoint( rPoly[ 0 ] );
     761           0 :                 ImplEndRecord();
     762           0 :                 n++;
     763           0 :                 continue;
     764             :             }
     765             : 
     766           0 :             sal_uInt16 nBezPoints = 0;
     767             : 
     768           0 :             while ( ( ( nBezPoints + n + 2 ) < rPoly.GetSize() ) && ( rPoly.GetFlags( nBezPoints + n ) == POLY_CONTROL ) )
     769           0 :                 nBezPoints += 3;
     770             : 
     771           0 :             if ( nBezPoints )
     772             :             {
     773           0 :                 ImplBeginRecord( WIN_EMR_POLYBEZIERTO );
     774           0 :                 Polygon aNewPoly( nBezPoints + 1 );
     775           0 :                 aNewPoly[ 0 ] = rPoly[ n - 1 ];
     776           0 :                 for ( o = 0; o < nBezPoints; o++ )
     777           0 :                     aNewPoly[ o + 1 ] = rPoly[ n + o ];
     778           0 :                 ImplWriteRect( aNewPoly.GetBoundRect() );
     779           0 :                 m_rStm.WriteUInt32( nBezPoints );
     780           0 :                 for( o = 1; o < aNewPoly.GetSize(); o++ )
     781           0 :                     ImplWritePoint( aNewPoly[ o ] );
     782           0 :                 ImplEndRecord();
     783           0 :                 n = n + nBezPoints;
     784             :             }
     785             :             else
     786             :             {
     787           0 :                 sal_uInt16 nPoints = 1;
     788           0 :                 while( ( nPoints + n ) < rPoly.GetSize() && ( rPoly.GetFlags( nPoints + n ) != POLY_CONTROL ) )
     789           0 :                     nPoints++;
     790             : 
     791           0 :                 if ( nPoints > 1 )
     792             :                 {
     793           0 :                     ImplBeginRecord( WIN_EMR_POLYLINETO );
     794           0 :                     Polygon aNewPoly( nPoints + 1 );
     795           0 :                     aNewPoly[ 0 ] = rPoly[ n - 1];
     796           0 :                     for ( o = 1; o <= nPoints; o++ )
     797           0 :                         aNewPoly[ o ] = rPoly[ n - 1 + o ];
     798           0 :                     ImplWriteRect( aNewPoly.GetBoundRect() );
     799           0 :                     m_rStm.WriteUInt32( nPoints );
     800           0 :                     for( o = 1; o < aNewPoly.GetSize(); o++ )
     801           0 :                         ImplWritePoint( aNewPoly[ o ] );
     802           0 :                     ImplEndRecord();
     803             :                 }
     804             :                 else
     805             :                 {
     806           0 :                     ImplBeginRecord( WIN_EMR_LINETO );
     807           0 :                     ImplWritePoint( rPoly[ n ] );
     808           0 :                     ImplEndRecord();
     809             :                 }
     810           0 :                 n = n + nPoints;
     811             :             }
     812           0 :             if ( bClosed && ( n == rPoly.GetSize() ) )
     813             :             {
     814           0 :                 ImplBeginRecord( WIN_EMR_CLOSEFIGURE );
     815           0 :                 ImplEndRecord();
     816             :             }
     817             :         }
     818             :     }
     819           0 :     ImplBeginRecord( WIN_EMR_ENDPATH );
     820           0 :     ImplEndRecord();
     821           0 :     ImplBeginRecord( bClosed ? WIN_EMR_FILLPATH : WIN_EMR_STROKEPATH );
     822           0 :     ImplWriteRect( rPolyPoly.GetBoundRect() );
     823           0 :     ImplEndRecord();
     824           0 : }
     825             : 
     826          28 : void EMFWriter::ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt,
     827             :                                     const Size& rSz, sal_uInt32 nROP )
     828             : {
     829          28 :     if( !!rBmp )
     830             :     {
     831          28 :         SvMemoryStream  aMemStm( 65535, 65535 );
     832          28 :         const Size      aBmpSizePixel( rBmp.GetSizePixel() );
     833             : 
     834          28 :         ImplBeginRecord( WIN_EMR_STRETCHDIBITS );
     835          28 :         ImplWriteRect( Rectangle( rPt, rSz ) );
     836          28 :         ImplWritePoint( rPt );
     837          28 :         m_rStm.WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aBmpSizePixel.Width() ).WriteInt32( aBmpSizePixel.Height() );
     838             : 
     839             :         // write offset positions and sizes later
     840          28 :         const sal_uLong nOffPos = m_rStm.Tell();
     841          28 :         m_rStm.SeekRel( 16 );
     842             : 
     843          28 :         m_rStm.WriteUInt32( 0 ).WriteInt32( ( ROP_XOR == maVDev->GetRasterOp() && WIN_SRCCOPY == nROP ) ? WIN_SRCINVERT : nROP );
     844          28 :         ImplWriteSize( rSz );
     845             : 
     846          28 :         WriteDIB(rBmp, aMemStm, true, false);
     847             : 
     848          28 :         sal_uInt32  nDIBSize = aMemStm.Tell(), nHeaderSize, nCompression, nColsUsed, nPalCount, nImageSize;
     849             :         sal_uInt16  nBitCount;
     850             : 
     851             :         // get DIB parameters
     852          28 :         aMemStm.Seek( 0 );
     853          28 :         aMemStm.ReadUInt32( nHeaderSize );
     854          28 :         aMemStm.SeekRel( 10 );
     855          28 :         aMemStm.ReadUInt16( nBitCount ).ReadUInt32( nCompression ).ReadUInt32( nImageSize );
     856          28 :         aMemStm.SeekRel( 8 );
     857          28 :         aMemStm.ReadUInt32( nColsUsed );
     858             : 
     859          28 :         if (nBitCount <= 8)
     860             :         {
     861          11 :             if (nColsUsed)
     862          11 :                 nPalCount = nColsUsed;
     863             :             else
     864           0 :                 nPalCount = 1 << (sal_uInt32)nBitCount;
     865             :         }
     866             :         else
     867             :         {
     868          17 :             if (nCompression == BITFIELDS)
     869          17 :                 nPalCount = 3;
     870             :             else
     871           0 :                 nPalCount = 0;
     872             :         }
     873             : 
     874          28 :         sal_uInt32 nPalSize = nPalCount * 4;
     875             : 
     876          28 :         m_rStm.Write( aMemStm.GetData(), nDIBSize );
     877             : 
     878          28 :         const sal_uLong nEndPos = m_rStm.Tell();
     879          28 :         m_rStm.Seek( nOffPos );
     880          28 :         m_rStm.WriteUInt32( 80 ).WriteUInt32( nHeaderSize + nPalSize );
     881          28 :         m_rStm.WriteUInt32( 80 + nHeaderSize + nPalSize ).WriteUInt32( nImageSize );
     882          28 :         m_rStm.Seek( nEndPos );
     883             : 
     884          28 :         ImplEndRecord();
     885             :     }
     886          28 : }
     887             : 
     888         404 : void EMFWriter::ImplWriteTextRecord( const Point& rPos, const OUString& rText, const long* pDXArray, sal_uInt32 nWidth )
     889             : {
     890         404 :     sal_Int32 nLen = rText.getLength(), i;
     891             : 
     892         404 :     if( nLen )
     893             :     {
     894             :         sal_uInt32  nNormWidth;
     895         404 :         boost::scoped_array<long> pOwnArray;
     896             :         long*  pDX;
     897             : 
     898             :         // get text sizes
     899         404 :         if( pDXArray )
     900             :         {
     901          60 :             nNormWidth = maVDev->GetTextWidth( rText );
     902          60 :             pDX = const_cast<long*>(pDXArray);
     903             :         }
     904             :         else
     905             :         {
     906         344 :             pOwnArray.reset(new long[ nLen ]);
     907         344 :             nNormWidth = maVDev->GetTextArray( rText, pOwnArray.get() );
     908         344 :             pDX = pOwnArray.get();
     909             :         }
     910             : 
     911         404 :         if( nLen > 1 )
     912             :         {
     913          64 :             nNormWidth = pDX[ nLen - 2 ] + maVDev->GetTextWidth( OUString(rText[ nLen - 1 ]) );
     914             : 
     915          64 :             if( nWidth && nNormWidth && ( nWidth != nNormWidth ) )
     916             :             {
     917          23 :                 const double fFactor = (double) nWidth / nNormWidth;
     918             : 
     919          68 :                 for( i = 0; i < ( nLen - 1 ); i++ )
     920          45 :                     pDX[ i ] = FRound( pDX[ i ] * fFactor );
     921             :             }
     922             :         }
     923             : 
     924             :         // write text record
     925         404 :         ImplBeginRecord( WIN_EMR_EXTTEXTOUTW );
     926             : 
     927         404 :         ImplWriteRect( Rectangle( rPos, Size( nNormWidth, maVDev->GetTextHeight() ) ) );
     928         404 :         m_rStm.WriteUInt32( 1 );
     929         404 :         m_rStm.WriteInt32( 0 ).WriteInt32( 0 );
     930         404 :         ImplWritePoint( rPos );
     931         404 :         m_rStm.WriteUInt32( nLen ).WriteUInt32( 76 ).WriteUInt32( 2 );
     932         404 :         m_rStm.WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( 0 );
     933         404 :         m_rStm.WriteUInt32( 76 + ( nLen << 1 ) + ( (nLen & 1 ) ? 2 : 0 ) );
     934             : 
     935             :         // write text
     936        1034 :         for( i = 0; i < nLen; i++ )
     937         630 :             m_rStm.WriteUInt16( rText[ i ] );
     938             : 
     939             :         // padding word
     940         404 :         if( nLen & 1 )
     941         366 :             m_rStm.WriteUInt16( 0 );
     942             : 
     943             :         // write DX array
     944         404 :         ImplWriteExtent( pDX[ 0 ] );
     945             : 
     946         404 :         if( nLen > 1 )
     947             :         {
     948         226 :             for( i = 1; i < ( nLen - 1 ); i++ )
     949         162 :                 ImplWriteExtent( pDX[ i ] - pDX[ i - 1 ] );
     950             : 
     951          64 :             ImplWriteExtent( pDX[ nLen - 2 ] / ( nLen - 1 ) );
     952             :         }
     953             : 
     954         404 :         ImplEndRecord();
     955             :     }
     956         404 : }
     957             : 
     958           0 : void EMFWriter::Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
     959             : {
     960           0 :     if(rLinePolygon.count())
     961             :     {
     962           0 :         basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
     963           0 :         basegfx::B2DPolyPolygon aFillPolyPolygon;
     964             : 
     965           0 :         rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
     966             : 
     967           0 :         if(aLinePolyPolygon.count())
     968             :         {
     969           0 :             for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
     970             :             {
     971           0 :                 const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
     972           0 :                 ImplWritePolygonRecord( Polygon(aCandidate), false );
     973           0 :             }
     974             :         }
     975             : 
     976           0 :         if(aFillPolyPolygon.count())
     977             :         {
     978           0 :             const Color aOldLineColor(maVDev->GetLineColor());
     979           0 :             const Color aOldFillColor(maVDev->GetFillColor());
     980             : 
     981           0 :             maVDev->SetLineColor();
     982           0 :             maVDev->SetFillColor(aOldLineColor);
     983             : 
     984           0 :             for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
     985             :             {
     986           0 :                 const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
     987           0 :                 ImplWritePolyPolygonRecord(tools::PolyPolygon(Polygon(aPolygon)));
     988           0 :             }
     989             : 
     990           0 :             maVDev->SetLineColor(aOldLineColor);
     991           0 :             maVDev->SetFillColor(aOldFillColor);
     992           0 :         }
     993             :     }
     994           0 : }
     995             : 
     996          93 : void EMFWriter::ImplWrite( const GDIMetaFile& rMtf )
     997             : {
     998        5452 :     for( size_t j = 0, nActionCount = rMtf.GetActionSize(); j < nActionCount; j++ )
     999             :     {
    1000        5359 :         const MetaAction*    pAction = rMtf.GetAction( j );
    1001        5359 :         const MetaActionType nType = pAction->GetType();
    1002             : 
    1003        5359 :         switch( nType )
    1004             :         {
    1005             :             case( MetaActionType::PIXEL ):
    1006             :             {
    1007           0 :                 const MetaPixelAction* pA = static_cast<const MetaPixelAction*>(pAction);
    1008             : 
    1009           0 :                 ImplCheckLineAttr();
    1010           0 :                 ImplBeginRecord( WIN_EMR_SETPIXELV );
    1011           0 :                 ImplWritePoint( pA->GetPoint() );
    1012           0 :                 ImplWriteColor( pA->GetColor() );
    1013           0 :                 ImplEndRecord();
    1014             :             }
    1015           0 :             break;
    1016             : 
    1017             :             case( MetaActionType::POINT ):
    1018             :             {
    1019           0 :                 if( maVDev->IsLineColor() )
    1020             :                 {
    1021           0 :                     const MetaPointAction* pA = static_cast<const MetaPointAction*>(pAction);
    1022             : 
    1023           0 :                     ImplCheckLineAttr();
    1024           0 :                     ImplBeginRecord( WIN_EMR_SETPIXELV );
    1025           0 :                     ImplWritePoint( pA->GetPoint() );
    1026           0 :                     ImplWriteColor( maVDev->GetLineColor() );
    1027           0 :                     ImplEndRecord();
    1028             :                 }
    1029             :             }
    1030           0 :             break;
    1031             : 
    1032             :             case( MetaActionType::LINE ):
    1033             :             {
    1034         819 :                 if( maVDev->IsLineColor() )
    1035             :                 {
    1036         819 :                     const MetaLineAction* pA = static_cast<const MetaLineAction*>(pAction);
    1037             : 
    1038         819 :                     if(pA->GetLineInfo().IsDefault())
    1039             :                     {
    1040         819 :                         ImplCheckLineAttr();
    1041             : 
    1042         819 :                         ImplBeginRecord( WIN_EMR_MOVETOEX );
    1043         819 :                         ImplWritePoint( pA->GetStartPoint() );
    1044         819 :                         ImplEndRecord();
    1045             : 
    1046         819 :                         ImplBeginRecord( WIN_EMR_LINETO );
    1047         819 :                         ImplWritePoint( pA->GetEndPoint() );
    1048         819 :                         ImplEndRecord();
    1049             : 
    1050         819 :                         ImplBeginRecord( WIN_EMR_SETPIXELV );
    1051         819 :                         ImplWritePoint( pA->GetEndPoint() );
    1052         819 :                         ImplWriteColor( maVDev->GetLineColor() );
    1053         819 :                         ImplEndRecord();
    1054             :                     }
    1055             :                     else
    1056             :                     {
    1057             :                         // LineInfo used; handle Dash/Dot and fat lines
    1058           0 :                         basegfx::B2DPolygon aPolygon;
    1059           0 :                         aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
    1060           0 :                         aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
    1061           0 :                         Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
    1062             :                     }
    1063             :                 }
    1064             :             }
    1065         819 :             break;
    1066             : 
    1067             :             case( MetaActionType::RECT ):
    1068             :             {
    1069         144 :                 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
    1070             :                 {
    1071         128 :                     const MetaRectAction* pA = static_cast<const MetaRectAction*>(pAction);
    1072             : 
    1073         128 :                     ImplCheckFillAttr();
    1074         128 :                     ImplCheckLineAttr();
    1075             : 
    1076         128 :                     ImplBeginRecord( WIN_EMR_RECTANGLE );
    1077         128 :                     ImplWriteRect( pA->GetRect() );
    1078         128 :                     ImplEndRecord();
    1079             :                 }
    1080             :             }
    1081         144 :             break;
    1082             : 
    1083             :             case( MetaActionType::ROUNDRECT ):
    1084             :             {
    1085           0 :                 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
    1086             :                 {
    1087           0 :                     const MetaRoundRectAction* pA = static_cast<const MetaRoundRectAction*>(pAction);
    1088             : 
    1089           0 :                     ImplCheckFillAttr();
    1090           0 :                     ImplCheckLineAttr();
    1091             : 
    1092           0 :                     ImplBeginRecord( WIN_EMR_ROUNDRECT );
    1093           0 :                     ImplWriteRect( pA->GetRect() );
    1094           0 :                     ImplWriteSize( Size( pA->GetHorzRound(), pA->GetVertRound() ) );
    1095           0 :                     ImplEndRecord();
    1096             :                 }
    1097             :             }
    1098           0 :             break;
    1099             : 
    1100             :             case( MetaActionType::ELLIPSE ):
    1101             :             {
    1102           0 :                 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
    1103             :                 {
    1104           0 :                     const MetaEllipseAction* pA = static_cast<const MetaEllipseAction*>(pAction);
    1105             : 
    1106           0 :                     ImplCheckFillAttr();
    1107           0 :                     ImplCheckLineAttr();
    1108             : 
    1109           0 :                     ImplBeginRecord( WIN_EMR_ELLIPSE );
    1110           0 :                     ImplWriteRect( pA->GetRect() );
    1111           0 :                     ImplEndRecord();
    1112             :                 }
    1113             :             }
    1114           0 :             break;
    1115             : 
    1116             :             case( MetaActionType::ARC ):
    1117             :             case( MetaActionType::PIE ):
    1118             :             case( MetaActionType::CHORD ):
    1119             :             case( MetaActionType::POLYGON ):
    1120             :             {
    1121           0 :                 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
    1122             :                 {
    1123           0 :                     Polygon aPoly;
    1124             : 
    1125           0 :                     switch( nType )
    1126             :                     {
    1127             :                         case( MetaActionType::ARC ):
    1128             :                         {
    1129           0 :                             const MetaArcAction* pA = static_cast<const MetaArcAction*>(pAction);
    1130           0 :                             aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC );
    1131             :                         }
    1132           0 :                         break;
    1133             : 
    1134             :                         case( MetaActionType::PIE ):
    1135             :                         {
    1136           0 :                             const MetaPieAction* pA = static_cast<const MetaPieAction*>(pAction);
    1137           0 :                             aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE );
    1138             :                         }
    1139           0 :                         break;
    1140             : 
    1141             :                         case( MetaActionType::CHORD ):
    1142             :                         {
    1143           0 :                             const MetaChordAction* pA = static_cast<const MetaChordAction*>(pAction);
    1144           0 :                             aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD );
    1145             :                         }
    1146           0 :                         break;
    1147             : 
    1148             :                         case( MetaActionType::POLYGON ):
    1149           0 :                             aPoly = static_cast<const MetaPolygonAction*>(pAction)->GetPolygon();
    1150           0 :                         break;
    1151           0 :                         default: break;
    1152             :                     }
    1153             : 
    1154           0 :                     ImplWritePolygonRecord( aPoly, nType != MetaActionType::ARC );
    1155             :                 }
    1156             :             }
    1157           0 :             break;
    1158             : 
    1159             :             case( MetaActionType::POLYLINE ):
    1160             :             {
    1161          18 :                 if( maVDev->IsLineColor() )
    1162             :                 {
    1163          18 :                     const MetaPolyLineAction*   pA = static_cast<const MetaPolyLineAction*>(pAction);
    1164          18 :                     const Polygon&              rPoly = pA->GetPolygon();
    1165             : 
    1166          18 :                     if( rPoly.GetSize() )
    1167             :                     {
    1168          18 :                         if(pA->GetLineInfo().IsDefault())
    1169             :                         {
    1170          18 :                             ImplWritePolygonRecord( rPoly, false );
    1171             :                         }
    1172             :                         else
    1173             :                         {
    1174             :                             // LineInfo used; handle Dash/Dot and fat lines
    1175           0 :                             Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
    1176             :                         }
    1177             :                     }
    1178             :                 }
    1179             :             }
    1180          18 :             break;
    1181             : 
    1182             :             case( MetaActionType::POLYPOLYGON ):
    1183             :             {
    1184          12 :                 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
    1185          12 :                     ImplWritePolyPolygonRecord( static_cast<const MetaPolyPolygonAction*>(pAction)->GetPolyPolygon() );
    1186             :             }
    1187          12 :             break;
    1188             : 
    1189             :             case( MetaActionType::GRADIENT ):
    1190             :             {
    1191           0 :                 const MetaGradientAction*   pA = static_cast<const MetaGradientAction*>(pAction);
    1192           0 :                 GDIMetaFile                 aTmpMtf;
    1193             : 
    1194           0 :                 maVDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
    1195           0 :                 ImplWrite( aTmpMtf );
    1196             :             }
    1197           0 :             break;
    1198             : 
    1199             :             case MetaActionType::HATCH:
    1200             :             {
    1201          14 :                 const MetaHatchAction*  pA = static_cast<const MetaHatchAction*>(pAction);
    1202          14 :                 GDIMetaFile             aTmpMtf;
    1203             : 
    1204          14 :                 maVDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
    1205          14 :                 ImplWrite( aTmpMtf );
    1206             :             }
    1207          14 :             break;
    1208             : 
    1209             :             case MetaActionType::Transparent:
    1210             :             {
    1211           0 :                 const tools::PolyPolygon& rPolyPoly = static_cast<const MetaTransparentAction*>(pAction)->GetPolyPolygon();
    1212           0 :                 if( rPolyPoly.Count() )
    1213           0 :                     ImplWritePlusFillPolygonRecord( rPolyPoly[0], static_cast<const MetaTransparentAction*>(pAction)->GetTransparence() );
    1214           0 :                 ImplCheckFillAttr();
    1215           0 :                 ImplCheckLineAttr();
    1216           0 :                 ImplWritePolyPolygonRecord( rPolyPoly );
    1217             : 
    1218           0 :                 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS );
    1219           0 :                 ImplPlusRecord( EmfPlusGetDC, 0x00 );
    1220           0 :                 ImplEndCommentRecord();
    1221             :             }
    1222           0 :             break;
    1223             : 
    1224             :             case MetaActionType::FLOATTRANSPARENT:
    1225             :             {
    1226           0 :                 const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pAction);
    1227             : 
    1228           0 :                 GDIMetaFile     aTmpMtf( pA->GetGDIMetaFile() );
    1229           0 :                 Point           aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
    1230           0 :                 const Size      aSrcSize( aTmpMtf.GetPrefSize() );
    1231           0 :                 const Point     aDestPt( pA->GetPoint() );
    1232           0 :                 const Size      aDestSize( pA->GetSize() );
    1233           0 :                 const double    fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
    1234           0 :                 const double    fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
    1235             :                 long            nMoveX, nMoveY;
    1236             : 
    1237           0 :                 if( fScaleX != 1.0 || fScaleY != 1.0 )
    1238             :                 {
    1239           0 :                     aTmpMtf.Scale( fScaleX, fScaleY );
    1240           0 :                     aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
    1241             :                 }
    1242             : 
    1243           0 :                 nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
    1244             : 
    1245           0 :                 if( nMoveX || nMoveY )
    1246           0 :                     aTmpMtf.Move( nMoveX, nMoveY );
    1247             : 
    1248           0 :                 ImplCheckFillAttr();
    1249           0 :                 ImplCheckLineAttr();
    1250           0 :                 ImplCheckTextAttr();
    1251           0 :                 ImplWrite( aTmpMtf );
    1252             :             }
    1253           0 :             break;
    1254             : 
    1255             :             case( MetaActionType::EPS ):
    1256             :             {
    1257           0 :                 const MetaEPSAction*    pA = static_cast<const MetaEPSAction*>(pAction);
    1258           0 :                 const GDIMetaFile       aSubstitute( pA->GetSubstitute() );
    1259             : 
    1260           0 :                 for( size_t i = 0, nCount = aSubstitute.GetActionSize(); i < nCount; i++ )
    1261             :                 {
    1262           0 :                     const MetaAction* pSubstAct = aSubstitute.GetAction( i );
    1263           0 :                     if( pSubstAct->GetType() == MetaActionType::BMPSCALE )
    1264             :                     {
    1265           0 :                         maVDev->Push( PushFlags::ALL );
    1266           0 :                         ImplBeginRecord( WIN_EMR_SAVEDC );
    1267           0 :                         ImplEndRecord();
    1268             : 
    1269           0 :                         MapMode aMapMode( aSubstitute.GetPrefMapMode() );
    1270           0 :                         Size aOutSize( OutputDevice::LogicToLogic( pA->GetSize(), maVDev->GetMapMode(), aMapMode ) );
    1271           0 :                         aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) );
    1272           0 :                         aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) );
    1273           0 :                         aMapMode.SetOrigin( OutputDevice::LogicToLogic( pA->GetPoint(), maVDev->GetMapMode(), aMapMode ) );
    1274           0 :                         maVDev->SetMapMode( aMapMode );
    1275           0 :                         ImplWrite( aSubstitute );
    1276             : 
    1277           0 :                         maVDev->Pop();
    1278           0 :                         ImplBeginRecord( WIN_EMR_RESTOREDC );
    1279           0 :                         m_rStm.WriteInt32( -1 );
    1280           0 :                         ImplEndRecord();
    1281           0 :                         break;
    1282             :                     }
    1283           0 :                 }
    1284             :             }
    1285           0 :             break;
    1286             : 
    1287             :             case MetaActionType::BMP:
    1288             :             {
    1289           0 :                 const MetaBmpAction* pA = static_cast<const MetaBmpAction *>(pAction);
    1290           0 :                 ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), maVDev->PixelToLogic( pA->GetBitmap().GetSizePixel() ), WIN_SRCCOPY );
    1291             :             }
    1292           0 :             break;
    1293             : 
    1294             :             case MetaActionType::BMPSCALE:
    1295             :             {
    1296           6 :                 const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
    1297           6 :                 ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY );
    1298             :             }
    1299           6 :             break;
    1300             : 
    1301             :             case MetaActionType::BMPSCALEPART:
    1302             :             {
    1303           0 :                 const MetaBmpScalePartAction*   pA = static_cast<const MetaBmpScalePartAction*>(pAction);
    1304           0 :                 Bitmap                          aTmp( pA->GetBitmap() );
    1305             : 
    1306           0 :                 if( aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
    1307           0 :                     ImplWriteBmpRecord( aTmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY );
    1308             :             }
    1309           0 :             break;
    1310             : 
    1311             :             case MetaActionType::BMPEX:
    1312             :             {
    1313           2 :                 const MetaBmpExAction*  pA = static_cast<const MetaBmpExAction *>(pAction);
    1314           2 :                 Bitmap                  aBmp( pA->GetBitmapEx().GetBitmap() );
    1315           4 :                 Bitmap                  aMsk( pA->GetBitmapEx().GetMask() );
    1316             : 
    1317           2 :                 if( !!aMsk )
    1318             :                 {
    1319           2 :                     aBmp.Replace( aMsk, COL_WHITE );
    1320           2 :                     aMsk.Invert();
    1321           2 :                     ImplWriteBmpRecord( aMsk, pA->GetPoint(), maVDev->PixelToLogic( aMsk.GetSizePixel() ), WIN_SRCPAINT );
    1322           2 :                     ImplWriteBmpRecord( aBmp, pA->GetPoint(), maVDev->PixelToLogic( aBmp.GetSizePixel() ), WIN_SRCAND );
    1323             :                 }
    1324             :                 else
    1325           2 :                     ImplWriteBmpRecord( aBmp, pA->GetPoint(), aBmp.GetSizePixel(), WIN_SRCCOPY );
    1326             :             }
    1327           2 :             break;
    1328             : 
    1329             :             case MetaActionType::BMPEXSCALE:
    1330             :             {
    1331          12 :                 const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
    1332          12 :                 Bitmap                      aBmp( pA->GetBitmapEx().GetBitmap() );
    1333          24 :                 Bitmap                      aMsk( pA->GetBitmapEx().GetMask() );
    1334             : 
    1335          12 :                 if( !!aMsk )
    1336             :                 {
    1337           6 :                     aBmp.Replace( aMsk, COL_WHITE );
    1338           6 :                     aMsk.Invert();
    1339           6 :                     ImplWriteBmpRecord( aMsk, pA->GetPoint(), pA->GetSize(), WIN_SRCPAINT );
    1340           6 :                     ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCAND );
    1341             :                 }
    1342             :                 else
    1343          18 :                     ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY );
    1344             :             }
    1345          12 :             break;
    1346             : 
    1347             :             case MetaActionType::BMPEXSCALEPART:
    1348             :             {
    1349           0 :                 const MetaBmpExScalePartAction* pA = static_cast<const MetaBmpExScalePartAction*>(pAction);
    1350           0 :                 BitmapEx                        aBmpEx( pA->GetBitmapEx() );
    1351           0 :                 aBmpEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
    1352           0 :                 Bitmap                          aBmp( aBmpEx.GetBitmap() );
    1353           0 :                 Bitmap                          aMsk( aBmpEx.GetMask() );
    1354             : 
    1355           0 :                 if( !!aMsk )
    1356             :                 {
    1357           0 :                     aBmp.Replace( aMsk, COL_WHITE );
    1358           0 :                     aMsk.Invert();
    1359           0 :                     ImplWriteBmpRecord( aMsk, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCPAINT );
    1360           0 :                     ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCAND );
    1361             :                 }
    1362             :                 else
    1363           0 :                     ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY );
    1364             :             }
    1365           0 :             break;
    1366             : 
    1367             :             case MetaActionType::TEXT:
    1368             :             {
    1369           0 :                 const MetaTextAction*   pA = static_cast<const MetaTextAction*>(pAction);
    1370           0 :                 const OUString          aText = pA->GetText().copy( pA->GetIndex(), std::min(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
    1371             : 
    1372           0 :                 ImplCheckTextAttr();
    1373           0 :                 ImplWriteTextRecord( pA->GetPoint(), aText, NULL, 0 );
    1374             :             }
    1375           0 :             break;
    1376             : 
    1377             :             case MetaActionType::TEXTRECT:
    1378             :             {
    1379           0 :                 const MetaTextRectAction*   pA = static_cast<const MetaTextRectAction*>(pAction);
    1380           0 :                 const OUString              aText( pA->GetText() );
    1381             : 
    1382           0 :                 ImplCheckTextAttr();
    1383           0 :                 ImplWriteTextRecord( pA->GetRect().TopLeft(), aText, NULL, 0 );
    1384             :             }
    1385           0 :             break;
    1386             : 
    1387             :             case MetaActionType::TEXTARRAY:
    1388             :             {
    1389          60 :                 const MetaTextArrayAction*  pA = static_cast<const MetaTextArrayAction*>(pAction);
    1390          60 :                 const OUString              aText = pA->GetText().copy( pA->GetIndex(), std::min(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
    1391             : 
    1392          60 :                 ImplCheckTextAttr();
    1393          60 :                 ImplWriteTextRecord( pA->GetPoint(), aText, pA->GetDXArray(), 0 );
    1394             :             }
    1395          60 :             break;
    1396             : 
    1397             :             case MetaActionType::STRETCHTEXT:
    1398             :             {
    1399         344 :                 const MetaStretchTextAction*    pA = static_cast<const MetaStretchTextAction*>(pAction);
    1400         344 :                 const OUString                  aText = pA->GetText().copy( pA->GetIndex(), std::min(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
    1401             : 
    1402         344 :                 ImplCheckTextAttr();
    1403         344 :                 ImplWriteTextRecord( pA->GetPoint(), aText, NULL, pA->GetWidth() );
    1404             :             }
    1405         344 :             break;
    1406             : 
    1407             :             case( MetaActionType::LINECOLOR ):
    1408             :             {
    1409         312 :                 const_cast<MetaAction*>(pAction)->Execute( maVDev );
    1410         312 :                 mbLineChanged = true;
    1411             :             }
    1412         312 :             break;
    1413             : 
    1414             :             case( MetaActionType::FILLCOLOR ):
    1415             :             {
    1416          73 :                 const_cast<MetaAction*>(pAction)->Execute( maVDev );
    1417          73 :                 mbFillChanged = true;
    1418             :             }
    1419          73 :             break;
    1420             : 
    1421             :             case( MetaActionType::TEXTCOLOR ):
    1422             :             case( MetaActionType::TEXTLINECOLOR ):
    1423             :             case( MetaActionType::TEXTFILLCOLOR ):
    1424             :             case( MetaActionType::TEXTALIGN ):
    1425             :             case( MetaActionType::FONT ):
    1426             :             {
    1427        1695 :                 const_cast<MetaAction*>(pAction)->Execute( maVDev );
    1428        1695 :                 mbTextChanged = true;
    1429             :             }
    1430        1695 :             break;
    1431             : 
    1432             :             case( MetaActionType::ISECTRECTCLIPREGION ):
    1433             :             {
    1434          45 :                 const_cast<MetaAction*>(pAction)->Execute( maVDev );
    1435             : 
    1436          45 :                 ImplBeginRecord( WIN_EMR_INTERSECTCLIPRECT );
    1437          45 :                 ImplWriteRect( static_cast<const MetaISectRectClipRegionAction*>(pAction)->GetRect() );
    1438          45 :                 ImplEndRecord();
    1439             :             }
    1440          45 :             break;
    1441             : 
    1442             :             case( MetaActionType::CLIPREGION ):
    1443             :             case( MetaActionType::ISECTREGIONCLIPREGION ):
    1444             :             case( MetaActionType::MOVECLIPREGION ):
    1445             :             {
    1446           7 :                 const_cast<MetaAction*>(pAction)->Execute( maVDev );
    1447             :             }
    1448           7 :             break;
    1449             : 
    1450             :             case( MetaActionType::REFPOINT ):
    1451             :             case( MetaActionType::MAPMODE ):
    1452          11 :                 const_cast<MetaAction*>(pAction)->Execute( maVDev );
    1453          11 :             break;
    1454             : 
    1455             :             case( MetaActionType::PUSH ):
    1456             :             {
    1457         524 :                 const_cast<MetaAction*>(pAction)->Execute( maVDev );
    1458             : 
    1459         524 :                 ImplBeginRecord( WIN_EMR_SAVEDC );
    1460         524 :                 ImplEndRecord();
    1461             :             }
    1462         524 :             break;
    1463             : 
    1464             :             case( MetaActionType::POP ):
    1465             :             {
    1466         524 :                 const_cast<MetaAction*>(pAction)->Execute( maVDev );
    1467             : 
    1468         524 :                 ImplBeginRecord( WIN_EMR_RESTOREDC );
    1469         524 :                 m_rStm.WriteInt32( -1 );
    1470         524 :                 ImplEndRecord();
    1471             : 
    1472         524 :                 ImplWriteRasterOp( maVDev->GetRasterOp() );
    1473         524 :                 mbLineChanged = mbFillChanged = mbTextChanged = true;
    1474             :             }
    1475         524 :             break;
    1476             : 
    1477             :             case( MetaActionType::RASTEROP ):
    1478             :             {
    1479         317 :                 const_cast<MetaAction*>(pAction)->Execute( maVDev );
    1480         317 :                 ImplWriteRasterOp( static_cast<const MetaRasterOpAction*>(pAction)->GetRasterOp() );
    1481             :             }
    1482         317 :             break;
    1483             : 
    1484             :             case( MetaActionType::LAYOUTMODE ):
    1485             :             {
    1486          85 :                 ComplexTextLayoutMode nLayoutMode = static_cast<const MetaLayoutModeAction*>(pAction)->GetLayoutMode();
    1487          85 :                 mnHorTextAlign = 0;
    1488          85 :                 if ((nLayoutMode & TEXT_LAYOUT_BIDI_RTL) != TEXT_LAYOUT_DEFAULT)
    1489             :                 {
    1490           0 :                     mnHorTextAlign = TA_RIGHT | TA_RTLREADING;
    1491             :                 }
    1492          85 :                 if ((nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_RIGHT) != TEXT_LAYOUT_DEFAULT)
    1493           0 :                     mnHorTextAlign |= TA_RIGHT;
    1494          85 :                 else if ((nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT) != TEXT_LAYOUT_DEFAULT)
    1495           0 :                     mnHorTextAlign &= ~TA_RIGHT;
    1496          85 :                 break;
    1497             :             }
    1498             : 
    1499             :             case( MetaActionType::COMMENT ):
    1500             :             {
    1501             :                 MetaCommentAction const*const pCommentAction(
    1502         197 :                         static_cast<MetaCommentAction const*>(pAction));
    1503         197 :                 if (pCommentAction->GetComment() == "EMF_PLUS")
    1504             :                 {
    1505          60 :                     ImplBeginCommentRecord(WIN_EMR_COMMENT_EMFPLUS);
    1506          60 :                     m_rStm.Write(pCommentAction->GetData(),
    1507         120 :                                  pCommentAction->GetDataSize());
    1508          60 :                     ImplEndCommentRecord();
    1509             :                 }
    1510             :             }
    1511         197 :             break;
    1512             : 
    1513             :             case( MetaActionType::MASK ):
    1514             :             case( MetaActionType::MASKSCALE ):
    1515             :             case( MetaActionType::MASKSCALEPART ):
    1516             :             case( MetaActionType::WALLPAPER ):
    1517             :             case( MetaActionType::TEXTLINE ):
    1518             :             case( MetaActionType::GRADIENTEX ):
    1519             :             {
    1520             :                 // !!! >>> we don't want to support these actions
    1521             :             }
    1522           0 :             break;
    1523             : 
    1524             :             default:
    1525             :                 OSL_FAIL(OStringBuffer(
    1526             :                     "EMFWriter::ImplWriteActions: unsupported MetaAction #" ).
    1527             :                      append(static_cast<sal_Int32>(nType)).getStr());
    1528         138 :             break;
    1529             :         }
    1530             :     }
    1531         894 : }
    1532             : 
    1533             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11