/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svtools.hxx" #include "emfwr.hxx" #include #include #include #include #include #include // ----------- // - Defines - // ----------- #define WIN_EMR_HEADER 1 #define WIN_EMR_POLYBEZIER 2 #define WIN_EMR_POLYGON 3 #define WIN_EMR_POLYLINE 4 #define WIN_EMR_POLYBEZIERTO 5 #define WIN_EMR_POLYLINETO 6 #define WIN_EMR_POLYPOLYLINE 7 #define WIN_EMR_POLYPOLYGON 8 #define WIN_EMR_SETWINDOWEXTEX 9 #define WIN_EMR_SETWINDOWORGEX 10 #define WIN_EMR_SETVIEWPORTEXTEX 11 #define WIN_EMR_SETVIEWPORTORGEX 12 #define WIN_EMR_SETBRUSHORGEX 13 #define WIN_EMR_EOF 14 #define WIN_EMR_SETPIXELV 15 #define WIN_EMR_SETMAPPERFLAGS 16 #define WIN_EMR_SETMAPMODE 17 #define WIN_EMR_SETBKMODE 18 #define WIN_EMR_SETPOLYFILLMODE 19 #define WIN_EMR_SETROP2 20 #define WIN_EMR_SETSTRETCHBLTMODE 21 #define WIN_EMR_SETTEXTALIGN 22 #define WIN_EMR_SETCOLORADJUSTMENT 23 #define WIN_EMR_SETTEXTCOLOR 24 #define WIN_EMR_SETBKCOLOR 25 #define WIN_EMR_OFFSETCLIPRGN 26 #define WIN_EMR_MOVETOEX 27 #define WIN_EMR_SETMETARGN 28 #define WIN_EMR_EXCLUDECLIPRECT 29 #define WIN_EMR_INTERSECTCLIPRECT 30 #define WIN_EMR_SCALEVIEWPORTEXTEX 31 #define WIN_EMR_SCALEWINDOWEXTEX 32 #define WIN_EMR_SAVEDC 33 #define WIN_EMR_RESTOREDC 34 #define WIN_EMR_SETWORLDTRANSFORM 35 #define WIN_EMR_MODIFYWORLDTRANSFORM 36 #define WIN_EMR_SELECTOBJECT 37 #define WIN_EMR_CREATEPEN 38 #define WIN_EMR_CREATEBRUSHINDIRECT 39 #define WIN_EMR_DELETEOBJECT 40 #define WIN_EMR_ANGLEARC 41 #define WIN_EMR_ELLIPSE 42 #define WIN_EMR_RECTANGLE 43 #define WIN_EMR_ROUNDRECT 44 #define WIN_EMR_ARC 45 #define WIN_EMR_CHORD 46 #define WIN_EMR_PIE 47 #define WIN_EMR_SELECTPALETTE 48 #define WIN_EMR_CREATEPALETTE 49 #define WIN_EMR_SETPALETTEENTRIES 50 #define WIN_EMR_RESIZEPALETTE 51 #define WIN_EMR_REALIZEPALETTE 52 #define WIN_EMR_EXTFLOODFILL 53 #define WIN_EMR_LINETO 54 #define WIN_EMR_ARCTO 55 #define WIN_EMR_POLYDRAW 56 #define WIN_EMR_SETARCDIRECTION 57 #define WIN_EMR_SETMITERLIMIT 58 #define WIN_EMR_BEGINPATH 59 #define WIN_EMR_ENDPATH 60 #define WIN_EMR_CLOSEFIGURE 61 #define WIN_EMR_FILLPATH 62 #define WIN_EMR_STROKEANDFILLPATH 63 #define WIN_EMR_STROKEPATH 64 #define WIN_EMR_FLATTENPATH 65 #define WIN_EMR_WIDENPATH 66 #define WIN_EMR_SELECTCLIPPATH 67 #define WIN_EMR_ABORTPATH 68 #define WIN_EMR_GDICOMMENT 70 #define WIN_EMR_FILLRGN 71 #define WIN_EMR_FRAMERGN 72 #define WIN_EMR_INVERTRGN 73 #define WIN_EMR_PAINTRGN 74 #define WIN_EMR_EXTSELECTCLIPRGN 75 #define WIN_EMR_BITBLT 76 #define WIN_EMR_STRETCHBLT 77 #define WIN_EMR_MASKBLT 78 #define WIN_EMR_PLGBLT 79 #define WIN_EMR_SETDIBITSTODEVICE 80 #define WIN_EMR_STRETCHDIBITS 81 #define WIN_EMR_EXTCREATEFONTINDIRECTW 82 #define WIN_EMR_EXTTEXTOUTA 83 #define WIN_EMR_EXTTEXTOUTW 84 #define WIN_EMR_POLYBEZIER16 85 #define WIN_EMR_POLYGON16 86 #define WIN_EMR_POLYLINE16 87 #define WIN_EMR_POLYBEZIERTO16 88 #define WIN_EMR_POLYLINETO16 89 #define WIN_EMR_POLYPOLYLINE16 90 #define WIN_EMR_POLYPOLYGON16 91 #define WIN_EMR_POLYDRAW16 92 #define WIN_EMR_CREATEMONOBRUSH 93 #define WIN_EMR_CREATEDIBPATTERNBRUSHPT 94 #define WIN_EMR_EXTCREATEPEN 95 #define WIN_EMR_POLYTEXTOUTA 96 #define WIN_EMR_POLYTEXTOUTW 97 #define WIN_SRCCOPY 0x00CC0020L #define WIN_SRCPAINT 0x00EE0086L #define WIN_SRCAND 0x008800C6L #define WIN_SRCINVERT 0x00660046L #define HANDLE_INVALID 0xffffffff #define MAXHANDLES 65000 #define LINE_SELECT 0x00000001 #define FILL_SELECT 0x00000002 #define TEXT_SELECT 0x00000004 /* Text Alignment Options */ #define TA_NOUPDATECP 0 #define TA_UPDATECP 1 #define TA_LEFT 0 #define TA_RIGHT 2 #define TA_CENTER 6 #define TA_TOP 0 #define TA_BOTTOM 8 #define TA_BASELINE 24 #define TA_RTLREADING 256 #define TA_MASK (TA_BASELINE+TA_CENTER+TA_UPDATECP+TA_RTLREADING) #define MM_ANISOTROPIC 8 // ------------- // - EMFWriter - // ------------- sal_Bool EMFWriter::WriteEMF( const GDIMetaFile& rMtf, FilterConfigItem* pFilterConfigItem ) { const sal_uLong nHeaderPos = m_rStm.Tell(); mpHandlesUsed = new sal_Bool[ MAXHANDLES ]; memset( mpHandlesUsed, 0, MAXHANDLES * sizeof( sal_Bool ) ); mnHorTextAlign = mnHandleCount = mnLastPercent = mnRecordPos = mnRecordCount = 0; mnLineHandle = mnFillHandle = mnTextHandle = HANDLE_INVALID; mbRecordOpen = sal_False; maVDev.EnableOutput( sal_False ); maVDev.SetMapMode( rMtf.GetPrefMapMode() ); mpFilterConfigItem = pFilterConfigItem; // don't work with pixel as destination map mode -> higher resolution preferrable maDestMapMode.SetMapUnit( MAP_100TH_MM ); const Size aMtfSizePix( maVDev.LogicToPixel( rMtf.GetPrefSize(), rMtf.GetPrefMapMode() ) ); const Size aMtfSizeLog( maVDev.LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_100TH_MM ) ); // seek over header // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits() m_rStm.SeekRel( 108 ); // write initial values // set 100th mm map mode in EMF ImplBeginRecord( WIN_EMR_SETMAPMODE ); m_rStm << (sal_Int32) MM_ANISOTROPIC; ImplEndRecord(); ImplBeginRecord( WIN_EMR_SETVIEWPORTEXTEX ); m_rStm << (sal_Int32) maVDev.ImplGetDPIX() << (sal_Int32) maVDev.ImplGetDPIY(); ImplEndRecord(); ImplBeginRecord( WIN_EMR_SETWINDOWEXTEX ); m_rStm << (sal_Int32) 2540 << (sal_Int32) 2540; ImplEndRecord(); ImplBeginRecord( WIN_EMR_SETVIEWPORTORGEX ); m_rStm << (sal_Int32) 0 << (sal_Int32) 0; ImplEndRecord(); ImplBeginRecord( WIN_EMR_SETWINDOWORGEX ); m_rStm << (sal_Int32) 0 << (sal_Int32) 0; ImplEndRecord(); ImplWriteRasterOp( ROP_OVERPAINT ); ImplBeginRecord( WIN_EMR_SETBKMODE ); m_rStm << (sal_uInt32) 1; // TRANSPARENT ImplEndRecord(); // write emf data ImplWrite( rMtf ); ImplBeginRecord( WIN_EMR_EOF ); m_rStm<< (sal_uInt32)0 // nPalEntries << (sal_uInt32)0x10 // offPalEntries << (sal_uInt32)0x14; // nSizeLast ImplEndRecord(); // write header const sal_uLong nEndPos = m_rStm.Tell(); m_rStm.Seek( nHeaderPos ); m_rStm << (sal_uInt32) 0x00000001 << (sal_uInt32) 108 //use [MS-EMF 2.2.11] HeaderExtension2 Object << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) ( aMtfSizePix.Width() - 1 ) << (sal_Int32) ( aMtfSizePix.Height() - 1 ) << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) ( aMtfSizeLog.Width() - 1 ) << (sal_Int32) ( aMtfSizeLog.Height() - 1 ) << (sal_uInt32) 0x464d4520 << (sal_uInt32) 0x10000 << (sal_uInt32) ( nEndPos - nHeaderPos ) << (sal_uInt32) mnRecordCount << (sal_uInt16) ( mnHandleCount + 1 ) << (sal_uInt16) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_Int32) aMtfSizePix.Width() << (sal_Int32) aMtfSizePix.Height() << (sal_Int32) ( aMtfSizeLog.Width() / 100 ) << (sal_Int32) ( aMtfSizeLog.Height() / 100 ) << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_Int32) ( aMtfSizeLog.Width() * 10 ) << (sal_Int32) ( aMtfSizeLog.Height() * 10 ); //use [MS-EMF 2.2.11] HeaderExtension2 Object m_rStm.Seek( nEndPos ); delete[] mpHandlesUsed; return( m_rStm.GetError() == ERRCODE_NONE ); } // ----------------------------------------------------------------------------- sal_uLong EMFWriter::ImplAcquireHandle() { sal_uLong nHandle = HANDLE_INVALID; for( sal_uLong i = 0; i < MAXHANDLES && ( HANDLE_INVALID == nHandle ); i++ ) { if( !mpHandlesUsed[ i ] ) { mpHandlesUsed[ i ] = sal_True; if( ( nHandle = i ) == mnHandleCount ) mnHandleCount++; } } DBG_ASSERT( nHandle != HANDLE_INVALID, "No more handles available" ); return( nHandle != HANDLE_INVALID ? nHandle + 1 : HANDLE_INVALID ); } // ----------------------------------------------------------------------------- void EMFWriter::ImplReleaseHandle( sal_uLong nHandle ) { DBG_ASSERT( nHandle && ( nHandle < MAXHANDLES ), "Handle out of range" ); mpHandlesUsed[ nHandle - 1 ] = sal_False; } // ----------------------------------------------------------------------------- void EMFWriter::ImplBeginRecord( sal_uInt32 nType ) { DBG_ASSERT( !mbRecordOpen, "Another record is already opened!" ); if( !mbRecordOpen ) { mbRecordOpen = sal_True; mnRecordPos = m_rStm.Tell(); m_rStm << nType; m_rStm.SeekRel( 4 ); } } // ----------------------------------------------------------------------------- void EMFWriter::ImplEndRecord() { DBG_ASSERT( mbRecordOpen, "Record was not opened!" ); if( mbRecordOpen ) { sal_Int32 nFillBytes, nActPos = m_rStm.Tell(); m_rStm.Seek( mnRecordPos + 4 ); nFillBytes = nActPos - mnRecordPos; nFillBytes += 3; // each record has to be dword aligned nFillBytes ^= 3; nFillBytes &= 3; m_rStm << (sal_uInt32)( ( nActPos - mnRecordPos ) + nFillBytes ); m_rStm.Seek( nActPos ); while( nFillBytes-- ) m_rStm << (sal_uInt8)0; mnRecordCount++; mbRecordOpen = sal_False; } } // ----------------------------------------------------------------------------- sal_Bool EMFWriter::ImplPrepareHandleSelect( sal_uInt32& rHandle, sal_uLong nSelectType ) { if( rHandle != HANDLE_INVALID ) { sal_uInt32 nStockObject = 0x80000000; if( LINE_SELECT == nSelectType ) nStockObject |= 0x00000007; else if( FILL_SELECT == nSelectType ) nStockObject |= 0x00000001; else if( TEXT_SELECT == nSelectType ) nStockObject |= 0x0000000a; // select stock object first ImplBeginRecord( WIN_EMR_SELECTOBJECT ); m_rStm << nStockObject; ImplEndRecord(); // destroy handle of created object ImplBeginRecord( WIN_EMR_DELETEOBJECT ); m_rStm << rHandle; ImplEndRecord(); // mark handle as free ImplReleaseHandle( rHandle ); } rHandle = ImplAcquireHandle(); return( HANDLE_INVALID != rHandle ); } // ----------------------------------------------------------------------------- void EMFWriter::ImplCheckLineAttr() { if( mbLineChanged && ImplPrepareHandleSelect( mnLineHandle, LINE_SELECT ) ) { sal_uInt32 nStyle = maVDev.IsLineColor() ? 0 : 5; sal_uInt32 nWidth = 0, nHeight = 0; ImplBeginRecord( WIN_EMR_CREATEPEN ); m_rStm << mnLineHandle << nStyle << nWidth << nHeight; ImplWriteColor( maVDev.GetLineColor() ); ImplEndRecord(); ImplBeginRecord( WIN_EMR_SELECTOBJECT ); m_rStm << mnLineHandle; ImplEndRecord(); } } // ----------------------------------------------------------------------------- void EMFWriter::ImplCheckFillAttr() { if( mbFillChanged && ImplPrepareHandleSelect( mnFillHandle, FILL_SELECT ) ) { sal_uInt32 nStyle = maVDev.IsFillColor() ? 0 : 1; sal_uInt32 nPatternStyle = 0; ImplBeginRecord( WIN_EMR_CREATEBRUSHINDIRECT ); m_rStm << mnFillHandle << nStyle; ImplWriteColor( maVDev.GetFillColor() ); m_rStm << nPatternStyle; ImplEndRecord(); ImplBeginRecord( WIN_EMR_SELECTOBJECT ); m_rStm << mnFillHandle; ImplEndRecord(); } } // ----------------------------------------------------------------------------- void EMFWriter::ImplCheckTextAttr() { if( mbTextChanged && ImplPrepareHandleSelect( mnTextHandle, TEXT_SELECT ) ) { const Font& rFont = maVDev.GetFont(); String aFontName( rFont.GetName() ); sal_Int32 nWeight; sal_uInt16 i; sal_uInt8 nPitchAndFamily; ImplBeginRecord( WIN_EMR_EXTCREATEFONTINDIRECTW ); m_rStm << mnTextHandle; ImplWriteExtent( -rFont.GetSize().Height() ); ImplWriteExtent( rFont.GetSize().Width() ); m_rStm << (sal_Int32) rFont.GetOrientation() << (sal_Int32) rFont.GetOrientation(); switch( rFont.GetWeight() ) { case WEIGHT_THIN: nWeight = 100; break; case WEIGHT_ULTRALIGHT: nWeight = 200; break; case WEIGHT_LIGHT: nWeight = 300; break; case WEIGHT_SEMILIGHT: nWeight = 300; break; case WEIGHT_NORMAL: nWeight = 400; break; case WEIGHT_MEDIUM: nWeight = 500; break; case WEIGHT_SEMIBOLD: nWeight = 600; break; case WEIGHT_BOLD: nWeight = 700; break; case WEIGHT_ULTRABOLD: nWeight = 800; break; case WEIGHT_BLACK: nWeight = 900; break; default: nWeight = 0; break; } m_rStm << nWeight; m_rStm << (sal_uInt8) ( ( ITALIC_NONE == rFont.GetItalic() ) ? 0 : 1 ); m_rStm << (sal_uInt8) ( ( UNDERLINE_NONE == rFont.GetUnderline() ) ? 0 : 1 ); m_rStm << (sal_uInt8) ( ( STRIKEOUT_NONE == rFont.GetStrikeout() ) ? 0 : 1 ); m_rStm << (sal_uInt8) ( ( RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet() ) ? 2 : 0 ); m_rStm << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0; switch( rFont.GetPitch() ) { case PITCH_FIXED: nPitchAndFamily = 0x01; break; case PITCH_VARIABLE: nPitchAndFamily = 0x02; break; default: nPitchAndFamily = 0x00; break; } switch( rFont.GetFamily() ) { case FAMILY_DECORATIVE: nPitchAndFamily |= 0x50; break; case FAMILY_MODERN: nPitchAndFamily |= 0x30; break; case FAMILY_ROMAN: nPitchAndFamily |= 0x10; break; case FAMILY_SCRIPT: nPitchAndFamily |= 0x40; break; case FAMILY_SWISS: nPitchAndFamily |= 0x20; break; default: break; } m_rStm << nPitchAndFamily; for( i = 0; i < 32; i++ ) m_rStm << (sal_Unicode) ( ( i < aFontName.Len() ) ? aFontName.GetChar( i ) : 0 ); // dummy elfFullName for( i = 0; i < 64; i++ ) m_rStm << (sal_Unicode) 0; // dummy elfStyle for( i = 0; i < 32; i++ ) m_rStm << (sal_Unicode) 0; // dummy elfVersion, elfStyleSize, elfMatch, elfReserved m_rStm << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 ; // dummy elfVendorId m_rStm << (sal_uInt32) 0; // dummy elfCulture m_rStm << (sal_uInt32) 0; // dummy elfPanose m_rStm << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0; // fill record to get a record size divideable by 4 m_rStm << (sal_uInt16) 0; ImplEndRecord(); // TextAlign sal_uInt32 nTextAlign; switch( rFont.GetAlign() ) { case ALIGN_TOP: nTextAlign = TA_TOP; break; case ALIGN_BOTTOM: nTextAlign = TA_BOTTOM; break; default: nTextAlign = TA_BASELINE; break; } nTextAlign |= mnHorTextAlign; ImplBeginRecord( WIN_EMR_SETTEXTALIGN ); m_rStm << nTextAlign; ImplEndRecord(); // Text color ImplBeginRecord( WIN_EMR_SETTEXTCOLOR ); ImplWriteColor( maVDev.GetTextColor() ); ImplEndRecord(); ImplBeginRecord( WIN_EMR_SELECTOBJECT ); m_rStm << mnTextHandle; ImplEndRecord(); } } // ----------------------------------------------------------------------------- void EMFWriter::ImplWriteColor( const Color& rColor ) { sal_uInt32 nCol = rColor.GetRed(); nCol |= ( (sal_uInt32) rColor.GetGreen() ) << 8; nCol |= ( (sal_uInt32) rColor.GetBlue() ) << 16; m_rStm << nCol; } // ----------------------------------------------------------------------------- void EMFWriter::ImplWriteRasterOp( RasterOp eRop ) { sal_uInt32 nROP2; switch( eRop ) { case ROP_INVERT: nROP2 = 6; break; case ROP_XOR: nROP2 = 7; break; default: nROP2 = 13;break; } ImplBeginRecord( WIN_EMR_SETROP2 ); m_rStm << nROP2; ImplEndRecord(); } // ----------------------------------------------------------------------------- void EMFWriter::ImplWriteExtent( long nExtent ) { nExtent = maVDev.LogicToLogic( Size( nExtent, 0 ), maVDev.GetMapMode(), maDestMapMode ).Width(); m_rStm << (sal_Int32) nExtent; } // ----------------------------------------------------------------------------- void EMFWriter::ImplWritePoint( const Point& rPoint ) { const Point aPoint( maVDev.LogicToLogic( rPoint, maVDev.GetMapMode(), maDestMapMode )); m_rStm << (sal_Int32) aPoint.X() << (sal_Int32) aPoint.Y(); } // ----------------------------------------------------------------------------- void EMFWriter::ImplWriteSize( const Size& rSize) { const Size aSize( maVDev.LogicToLogic( rSize, maVDev.GetMapMode(), maDestMapMode )); m_rStm << (sal_Int32) aSize.Width() << (sal_Int32) aSize.Height(); } // ----------------------------------------------------------------------------- void EMFWriter::ImplWriteRect( const Rectangle& rRect ) { const Rectangle aRect( maVDev.LogicToLogic ( rRect, maVDev.GetMapMode(), maDestMapMode )); m_rStm << aRect.Left() << aRect.Top() << aRect.Right() << aRect.Bottom(); } // ----------------------------------------------------------------------------- void EMFWriter::ImplWritePolygonRecord( const Polygon& rPoly, sal_Bool bClose ) { if( rPoly.GetSize() ) { if( rPoly.HasFlags() ) ImplWritePath( rPoly, bClose ); else { if( bClose ) ImplCheckFillAttr(); ImplCheckLineAttr(); ImplBeginRecord( bClose ? WIN_EMR_POLYGON : WIN_EMR_POLYLINE ); ImplWriteRect( rPoly.GetBoundRect() ); m_rStm << (sal_uInt32) rPoly.GetSize(); for( sal_uInt16 i = 0; i < rPoly.GetSize(); i++ ) ImplWritePoint( rPoly[ i ] ); ImplEndRecord(); } } } // ----------------------------------------------------------------------------- void EMFWriter::ImplWritePolyPolygonRecord( const PolyPolygon& rPolyPoly ) { sal_uInt16 n, i, nPolyCount = rPolyPoly.Count(); if( nPolyCount ) { if( 1 == nPolyCount ) ImplWritePolygonRecord( rPolyPoly[ 0 ], sal_True ); else { sal_Bool bHasFlags = sal_False; sal_uInt32 nTotalPoints = 0; for( i = 0; i < nPolyCount; i++ ) { nTotalPoints += rPolyPoly[ i ].GetSize(); if ( rPolyPoly[ i ].HasFlags() ) bHasFlags = sal_True; } if( nTotalPoints ) { if ( bHasFlags ) ImplWritePath( rPolyPoly, sal_True ); else { ImplCheckFillAttr(); ImplCheckLineAttr(); ImplBeginRecord( WIN_EMR_POLYPOLYGON ); ImplWriteRect( rPolyPoly.GetBoundRect() ); m_rStm << (sal_uInt32)nPolyCount << nTotalPoints; for( i = 0; i < nPolyCount; i++ ) m_rStm << (sal_uInt32)rPolyPoly[ i ].GetSize(); for( i = 0; i < nPolyCount; i++ ) { const Polygon& rPoly = rPolyPoly[ i ]; for( n = 0; n < rPoly.GetSize(); n++ ) ImplWritePoint( rPoly[ n ] ); } ImplEndRecord(); } } } } } // ----------------------------------------------------------------------------- void EMFWriter::ImplWritePath( const PolyPolygon& rPolyPoly, sal_Bool bClosed ) { if ( bClosed ) ImplCheckFillAttr(); ImplCheckLineAttr(); ImplBeginRecord( WIN_EMR_BEGINPATH ); ImplEndRecord(); sal_uInt16 i, n, o, nPolyCount = rPolyPoly.Count(); for ( i = 0; i < nPolyCount; i++ ) { n = 0; const Polygon& rPoly = rPolyPoly[ i ]; while ( n < rPoly.GetSize() ) { if( n == 0 ) { ImplBeginRecord( WIN_EMR_MOVETOEX ); ImplWritePoint( rPoly[ 0 ] ); ImplEndRecord(); n++; continue; } sal_uInt16 nBezPoints = 0; while ( ( ( nBezPoints + n + 2 ) < rPoly.GetSize() ) && ( rPoly.GetFlags( nBezPoints + n ) == POLY_CONTROL ) ) nBezPoints += 3; if ( nBezPoints ) { ImplBeginRecord( WIN_EMR_POLYBEZIERTO ); Polygon aNewPoly( nBezPoints + 1 ); aNewPoly[ 0 ] = rPoly[ n - 1 ]; for ( o = 0; o < nBezPoints; o++ ) aNewPoly[ o + 1 ] = rPoly[ n + o ]; ImplWriteRect( aNewPoly.GetBoundRect() ); m_rStm << (sal_uInt32)nBezPoints; for( o = 1; o < aNewPoly.GetSize(); o++ ) ImplWritePoint( aNewPoly[ o ] ); ImplEndRecord(); n = n + nBezPoints; } else { sal_uInt16 nPoints = 1; while( ( nPoints + n ) < rPoly.GetSize() && ( rPoly.GetFlags( nPoints + n ) != POLY_CONTROL ) ) nPoints++; if ( nPoints > 1 ) { ImplBeginRecord( WIN_EMR_POLYLINETO ); Polygon aNewPoly( nPoints + 1 ); aNewPoly[ 0 ] = rPoly[ n - 1]; for ( o = 1; o <= nPoints; o++ ) aNewPoly[ o ] = rPoly[ n - 1 + o ]; ImplWriteRect( aNewPoly.GetBoundRect() ); m_rStm << (sal_uInt32)( nPoints ); for( o = 1; o < aNewPoly.GetSize(); o++ ) ImplWritePoint( aNewPoly[ o ] ); ImplEndRecord(); } else { ImplBeginRecord( WIN_EMR_LINETO ); ImplWritePoint( rPoly[ n ] ); ImplEndRecord(); } n = n + nPoints; } if ( bClosed && ( n == rPoly.GetSize() ) ) { ImplBeginRecord( WIN_EMR_CLOSEFIGURE ); ImplEndRecord(); } } } ImplBeginRecord( WIN_EMR_ENDPATH ); ImplEndRecord(); ImplBeginRecord( bClosed ? WIN_EMR_FILLPATH : WIN_EMR_STROKEPATH ); ImplWriteRect( rPolyPoly.GetBoundRect() ); ImplEndRecord(); } // ----------------------------------------------------------------------------- void EMFWriter::ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt, const Size& rSz, sal_uInt32 nROP ) { if( !!rBmp ) { SvMemoryStream aMemStm( 65535, 65535 ); const Size aBmpSizePixel( rBmp.GetSizePixel() ); ImplBeginRecord( WIN_EMR_STRETCHDIBITS ); ImplWriteRect( Rectangle( rPt, rSz ) ); ImplWritePoint( rPt ); m_rStm << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) aBmpSizePixel.Width() << (sal_Int32) aBmpSizePixel.Height(); // write offset positions and sizes later const sal_uLong nOffPos = m_rStm.Tell(); m_rStm.SeekRel( 16 ); m_rStm << (sal_uInt32) 0 << ( ( ROP_XOR == maVDev.GetRasterOp() && WIN_SRCCOPY == nROP ) ? WIN_SRCINVERT : nROP ); ImplWriteSize( rSz ); rBmp.Write( aMemStm, sal_True, sal_False ); sal_uInt32 nDIBSize = aMemStm.Tell(), nHeaderSize, nCompression, nColsUsed, nPalCount, nImageSize; sal_uInt16 nBitCount; // get DIB parameters aMemStm.Seek( 0 ); aMemStm >> nHeaderSize; aMemStm.SeekRel( 10 ); aMemStm >> nBitCount >> nCompression >> nImageSize; aMemStm.SeekRel( 8 ); aMemStm >> nColsUsed; nPalCount = ( nBitCount <= 8 ) ? ( nColsUsed ? nColsUsed : ( 1 << (sal_uInt32) nBitCount ) ) : ( ( 3 == nCompression ) ? 12 : 0 ); m_rStm.Write( aMemStm.GetData(), nDIBSize ); const sal_uLong nEndPos = m_rStm.Tell(); m_rStm.Seek( nOffPos ); m_rStm << (sal_uInt32) 80 << (sal_uInt32)( nHeaderSize + ( nPalCount << 2 ) ); m_rStm << (sal_uInt32)( 80 + ( nHeaderSize + ( nPalCount << 2 ) ) ) << nImageSize; m_rStm.Seek( nEndPos ); ImplEndRecord(); } } // ----------------------------------------------------------------------------- void EMFWriter::ImplWriteTextRecord( const Point& rPos, const String rText, const sal_Int32* pDXArray, sal_uInt32 nWidth ) { xub_StrLen nLen = rText.Len(), i; if( nLen ) { sal_uInt32 nNormWidth; sal_Int32* pOwnArray; sal_Int32* pDX; // get text sizes if( pDXArray ) { pOwnArray = NULL; nNormWidth = maVDev.GetTextWidth( rText ); pDX = (sal_Int32*) pDXArray; } else { pOwnArray = new sal_Int32[ nLen ]; nNormWidth = maVDev.GetTextArray( rText, pOwnArray ); pDX = pOwnArray; } if( nLen > 1 ) { nNormWidth = pDX[ nLen - 2 ] + maVDev.GetTextWidth( rText.GetChar( nLen - 1 ) ); if( nWidth && nNormWidth && ( nWidth != nNormWidth ) ) { const double fFactor = (double) nWidth / nNormWidth; for( i = 0; i < ( nLen - 1 ); i++ ) pDX[ i ] = FRound( pDX[ i ] * fFactor ); } } // write text record ImplBeginRecord( WIN_EMR_EXTTEXTOUTW ); ImplWriteRect( Rectangle( rPos, Size( nNormWidth, maVDev.GetTextHeight() ) ) ); m_rStm << (sal_uInt32)1; m_rStm << (sal_Int32) 0 << (sal_Int32) 0; ImplWritePoint( rPos ); m_rStm << (sal_uInt32) nLen << (sal_uInt32) 76 << (sal_uInt32) 2; m_rStm << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) 0; m_rStm << (sal_uInt32) ( 76 + ( nLen << 1 ) + ( (nLen & 1 ) ? 2 : 0 ) ); // write text for( i = 0; i < nLen; i++ ) m_rStm << (sal_Unicode)rText.GetChar( i ); // padding word if( nLen & 1 ) m_rStm << (sal_uInt16) 0; // write DX array ImplWriteExtent( pDX[ 0 ] ); if( nLen > 1 ) { for( i = 1; i < ( nLen - 1 ); i++ ) ImplWriteExtent( pDX[ i ] - pDX[ i - 1 ] ); ImplWriteExtent( pDX[ nLen - 2 ] / ( nLen - 1 ) ); } ImplEndRecord(); delete[] pOwnArray; } } // ----------------------------------------------------------------------------- void EMFWriter::Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon) { if(rLinePolygon.count()) { basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon); basegfx::B2DPolyPolygon aFillPolyPolygon; rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon); if(aLinePolyPolygon.count()) { for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++) { const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a)); ImplWritePolygonRecord( Polygon(aCandidate), sal_False ); } } if(aFillPolyPolygon.count()) { const Color aOldLineColor(maVDev.GetLineColor()); const Color aOldFillColor(maVDev.GetFillColor()); maVDev.SetLineColor(); maVDev.SetFillColor(aOldLineColor); for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++) { const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a)); ImplWritePolyPolygonRecord(PolyPolygon(Polygon(aPolygon))); } maVDev.SetLineColor(aOldLineColor); maVDev.SetFillColor(aOldFillColor); } } } // ----------------------------------------------------------------------------- void EMFWriter::ImplWrite( const GDIMetaFile& rMtf ) { for( size_t j = 0, nActionCount = rMtf.GetActionSize(); j < nActionCount; j++ ) { const MetaAction* pAction = rMtf.GetAction( j ); const sal_uInt16 nType = pAction->GetType(); switch( nType ) { case( META_PIXEL_ACTION ): { const MetaPixelAction* pA = (const MetaPixelAction*) pAction; ImplCheckLineAttr(); ImplBeginRecord( WIN_EMR_SETPIXELV ); ImplWritePoint( pA->GetPoint() ); ImplWriteColor( pA->GetColor() ); ImplEndRecord(); } break; case( META_POINT_ACTION ): { if( maVDev.IsLineColor() ) { const MetaPointAction* pA = (const MetaPointAction*) pAction; ImplCheckLineAttr(); ImplBeginRecord( WIN_EMR_SETPIXELV ); ImplWritePoint( pA->GetPoint() ); ImplWriteColor( maVDev.GetLineColor() ); ImplEndRecord(); } } break; case( META_LINE_ACTION ): { if( maVDev.IsLineColor() ) { const MetaLineAction* pA = (const MetaLineAction*) pAction; if(pA->GetLineInfo().IsDefault()) { ImplCheckLineAttr(); ImplBeginRecord( WIN_EMR_MOVETOEX ); ImplWritePoint( pA->GetStartPoint() ); ImplEndRecord(); ImplBeginRecord( WIN_EMR_LINETO ); ImplWritePoint( pA->GetEndPoint() ); ImplEndRecord(); ImplBeginRecord( WIN_EMR_SETPIXELV ); ImplWritePoint( pA->GetEndPoint() ); ImplWriteColor( maVDev.GetLineColor() ); ImplEndRecord(); } else { // LineInfo used; handle Dash/Dot and fat lines basegfx::B2DPolygon aPolygon; aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y())); aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y())); Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon); } } } break; case( META_RECT_ACTION ): { if( maVDev.IsLineColor() || maVDev.IsFillColor() ) { const MetaRectAction* pA = (const MetaRectAction*) pAction; ImplCheckFillAttr(); ImplCheckLineAttr(); ImplBeginRecord( WIN_EMR_RECTANGLE ); ImplWriteRect( pA->GetRect() ); ImplEndRecord(); } } break; case( META_ROUNDRECT_ACTION ): { if( maVDev.IsLineColor() || maVDev.IsFillColor() ) { const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction; ImplCheckFillAttr(); ImplCheckLineAttr(); ImplBeginRecord( WIN_EMR_ROUNDRECT ); ImplWriteRect( pA->GetRect() ); ImplWriteSize( Size( pA->GetHorzRound(), pA->GetVertRound() ) ); ImplEndRecord(); } } break; case( META_ELLIPSE_ACTION ): { if( maVDev.IsLineColor() || maVDev.IsFillColor() ) { const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction; ImplCheckFillAttr(); ImplCheckLineAttr(); ImplBeginRecord( WIN_EMR_ELLIPSE ); ImplWriteRect( pA->GetRect() ); ImplEndRecord(); } } break; case( META_ARC_ACTION ): case( META_PIE_ACTION ): case( META_CHORD_ACTION ): case( META_POLYGON_ACTION ): { if( maVDev.IsLineColor() || maVDev.IsFillColor() ) { Polygon aPoly; switch( nType ) { case( META_ARC_ACTION ): { const MetaArcAction* pA = (const MetaArcAction*) pAction; aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC ); } break; case( META_PIE_ACTION ): { const MetaPieAction* pA = (const MetaPieAction*) pAction; aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE ); } break; case( META_CHORD_ACTION ): { const MetaChordAction* pA = (const MetaChordAction*) pAction; aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD ); } break; case( META_POLYGON_ACTION ): aPoly = ( (const MetaPolygonAction*) pAction )->GetPolygon(); break; } ImplWritePolygonRecord( aPoly, nType != META_ARC_ACTION ); } } break; case( META_POLYLINE_ACTION ): { if( maVDev.IsLineColor() ) { const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction; const Polygon& rPoly = pA->GetPolygon(); if( rPoly.GetSize() ) { if(pA->GetLineInfo().IsDefault()) { ImplWritePolygonRecord( rPoly, sal_False ); } else { // LineInfo used; handle Dash/Dot and fat lines Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon()); } } } } break; case( META_POLYPOLYGON_ACTION ): { if( maVDev.IsLineColor() || maVDev.IsFillColor() ) ImplWritePolyPolygonRecord( ( (const MetaPolyPolygonAction*) pAction )->GetPolyPolygon() ); } break; case( META_GRADIENT_ACTION ): { const MetaGradientAction* pA = (const MetaGradientAction*) pAction; GDIMetaFile aTmpMtf; maVDev.AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf ); ImplWrite( aTmpMtf ); } break; case META_HATCH_ACTION: { const MetaHatchAction* pA = (const MetaHatchAction*) pAction; GDIMetaFile aTmpMtf; maVDev.AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf ); ImplWrite( aTmpMtf ); } break; case META_TRANSPARENT_ACTION: { ImplCheckFillAttr(); ImplCheckLineAttr(); ImplWritePolyPolygonRecord( ( (MetaTransparentAction*) pAction )->GetPolyPolygon() ); } break; case META_FLOATTRANSPARENT_ACTION: { const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction; GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() ); Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() ); const Size aSrcSize( aTmpMtf.GetPrefSize() ); const Point aDestPt( pA->GetPoint() ); const Size aDestSize( pA->GetSize() ); const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0; const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0; long nMoveX, nMoveY; if( fScaleX != 1.0 || fScaleY != 1.0 ) { aTmpMtf.Scale( fScaleX, fScaleY ); aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY ); } nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y(); if( nMoveX || nMoveY ) aTmpMtf.Move( nMoveX, nMoveY ); ImplCheckFillAttr(); ImplCheckLineAttr(); ImplCheckTextAttr(); ImplWrite( aTmpMtf ); } break; case( META_EPS_ACTION ): { const MetaEPSAction* pA = (const MetaEPSAction*) pAction; const GDIMetaFile aSubstitute( pA->GetSubstitute() ); for( size_t i = 0, nCount = aSubstitute.GetActionSize(); i < nCount; i++ ) { const MetaAction* pSubstAct = aSubstitute.GetAction( i ); if( pSubstAct->GetType() == META_BMPSCALE_ACTION ) { maVDev.Push( PUSH_ALL ); ImplBeginRecord( WIN_EMR_SAVEDC ); ImplEndRecord(); MapMode aMapMode( aSubstitute.GetPrefMapMode() ); Size aOutSize( maVDev.LogicToLogic( pA->GetSize(), maVDev.GetMapMode(), aMapMode ) ); aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) ); aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) ); aMapMode.SetOrigin( maVDev.LogicToLogic( pA->GetPoint(), maVDev.GetMapMode(), aMapMode ) ); maVDev.SetMapMode( aMapMode ); ImplWrite( aSubstitute ); maVDev.Pop(); ImplBeginRecord( WIN_EMR_RESTOREDC ); m_rStm << (sal_Int32) -1; ImplEndRecord(); break; } } } break; case META_BMP_ACTION: { const MetaBmpAction* pA = (const MetaBmpAction *) pAction; ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), maVDev.PixelToLogic( pA->GetBitmap().GetSizePixel() ), WIN_SRCCOPY ); } break; case META_BMPSCALE_ACTION: { const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction; ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY ); } break; case META_BMPSCALEPART_ACTION: { const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction; Bitmap aTmp( pA->GetBitmap() ); if( aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) ) ImplWriteBmpRecord( aTmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY ); } break; case META_BMPEX_ACTION: { const MetaBmpExAction* pA = (const MetaBmpExAction *) pAction; Bitmap aBmp( pA->GetBitmapEx().GetBitmap() ); Bitmap aMsk( pA->GetBitmapEx().GetMask() ); if( !!aMsk ) { aBmp.Replace( aMsk, COL_WHITE ); aMsk.Invert(); ImplWriteBmpRecord( aMsk, pA->GetPoint(), maVDev.PixelToLogic( aMsk.GetSizePixel() ), WIN_SRCPAINT ); ImplWriteBmpRecord( aBmp, pA->GetPoint(), maVDev.PixelToLogic( aBmp.GetSizePixel() ), WIN_SRCAND ); } else ImplWriteBmpRecord( aBmp, pA->GetPoint(), aBmp.GetSizePixel(), WIN_SRCCOPY ); } break; case META_BMPEXSCALE_ACTION: { const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction; Bitmap aBmp( pA->GetBitmapEx().GetBitmap() ); Bitmap aMsk( pA->GetBitmapEx().GetMask() ); if( !!aMsk ) { aBmp.Replace( aMsk, COL_WHITE ); aMsk.Invert(); ImplWriteBmpRecord( aMsk, pA->GetPoint(), pA->GetSize(), WIN_SRCPAINT ); ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCAND ); } else ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY ); } break; case META_BMPEXSCALEPART_ACTION: { const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction; BitmapEx aBmpEx( pA->GetBitmapEx() ); aBmpEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ); Bitmap aBmp( aBmpEx.GetBitmap() ); Bitmap aMsk( aBmpEx.GetMask() ); if( !!aMsk ) { aBmp.Replace( aMsk, COL_WHITE ); aMsk.Invert(); ImplWriteBmpRecord( aMsk, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCPAINT ); ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCAND ); } else ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY ); } break; case META_TEXT_ACTION: { const MetaTextAction* pA = (const MetaTextAction*) pAction; const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() ); ImplCheckTextAttr(); ImplWriteTextRecord( pA->GetPoint(), aText, NULL, 0 ); } break; case META_TEXTRECT_ACTION: { const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction; const String aText( pA->GetText() ); ImplCheckTextAttr(); ImplWriteTextRecord( pA->GetRect().TopLeft(), aText, NULL, 0 ); } break; case META_TEXTARRAY_ACTION: { const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction; const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() ); ImplCheckTextAttr(); ImplWriteTextRecord( pA->GetPoint(), aText, pA->GetDXArray(), 0 ); } break; case META_STRETCHTEXT_ACTION: { const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction; const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() ); ImplCheckTextAttr(); ImplWriteTextRecord( pA->GetPoint(), aText, NULL, pA->GetWidth() ); } break; case( META_LINECOLOR_ACTION ): { ( (MetaAction*) pAction )->Execute( &maVDev ); mbLineChanged = sal_True; } break; case( META_FILLCOLOR_ACTION ): { ( (MetaAction*) pAction )->Execute( &maVDev ); mbFillChanged = sal_True; } break; case( META_TEXTCOLOR_ACTION ): case( META_TEXTLINECOLOR_ACTION ): case( META_TEXTFILLCOLOR_ACTION ): case( META_TEXTALIGN_ACTION ): case( META_FONT_ACTION ): { ( (MetaAction*) pAction )->Execute( &maVDev ); mbTextChanged = sal_True; } break; case( META_ISECTRECTCLIPREGION_ACTION ): { ( (MetaAction*) pAction )->Execute( &maVDev ); ImplBeginRecord( WIN_EMR_INTERSECTCLIPRECT ); ImplWriteRect( ( (MetaISectRectClipRegionAction*) pAction )->GetRect() ); ImplEndRecord(); } break; case( META_CLIPREGION_ACTION ): case( META_ISECTREGIONCLIPREGION_ACTION ): case( META_MOVECLIPREGION_ACTION ): { ( (MetaAction*) pAction )->Execute( &maVDev ); } break; case( META_REFPOINT_ACTION ): case( META_MAPMODE_ACTION ): ( (MetaAction*) pAction )->Execute( &maVDev ); break; case( META_PUSH_ACTION ): { ( (MetaAction*) pAction )->Execute( &maVDev ); ImplBeginRecord( WIN_EMR_SAVEDC ); ImplEndRecord(); } break; case( META_POP_ACTION ): { ( (MetaAction*) pAction )->Execute( &maVDev ); ImplBeginRecord( WIN_EMR_RESTOREDC ); m_rStm << (sal_Int32) -1; ImplEndRecord(); ImplWriteRasterOp( maVDev.GetRasterOp() ); mbLineChanged = mbFillChanged = mbTextChanged = sal_True; } break; case( META_RASTEROP_ACTION ): { ( (MetaAction*) pAction )->Execute( &maVDev ); ImplWriteRasterOp( ( (MetaRasterOpAction*) pAction )->GetRasterOp() ); } break; case( META_LAYOUTMODE_ACTION ): { sal_uInt32 nLayoutMode = ( (MetaLayoutModeAction*) pAction )->GetLayoutMode(); mnHorTextAlign = 0; if (nLayoutMode & TEXT_LAYOUT_BIDI_RTL) { mnHorTextAlign = TA_RIGHT | TA_RTLREADING; } if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_RIGHT) mnHorTextAlign |= TA_RIGHT; else if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT) mnHorTextAlign &= ~TA_RIGHT; break; } case( META_MASK_ACTION ): case( META_MASKSCALE_ACTION ): case( META_MASKSCALEPART_ACTION ): case( META_WALLPAPER_ACTION ): case( META_TEXTLINE_ACTION ): case( META_COMMENT_ACTION ): case( META_GRADIENTEX_ACTION ): { // !!! >>> we don't want to support these actions } break; case( META_RENDERGRAPHIC_ACTION ): { const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*) pAction; const ::vcl::RenderGraphicRasterizer aRasterizer( pA->GetRenderGraphic() ); const BitmapEx aBmpEx( aRasterizer.Rasterize( maVDev.LogicToPixel( pA->GetSize() ) ) ); Bitmap aBmp( aBmpEx.GetBitmap() ); Bitmap aMsk( aBmpEx.GetMask() ); if( !!aMsk ) { aBmp.Replace( aMsk, COL_WHITE ); aMsk.Invert(); ImplWriteBmpRecord( aMsk, pA->GetPoint(), pA->GetSize(), WIN_SRCPAINT ); ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCAND ); } else ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY ); } break; default: OSL_FAIL(rtl::OStringBuffer(RTL_CONSTASCII_STRINGPARAM( "EMFWriter::ImplWriteActions: unsupported MetaAction #" )). append(static_cast(nType)).getStr()); break; } } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */