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

Generated by: LCOV version 1.10