blob: 03d5c6269ea953588769f4f15f7dc4d6ac1db4b1 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"
#include "emfwr.hxx"
#include <vcl/salbtype.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <vcl/lineinfo.hxx>
#include <vcl/dibtools.hxx>
// -----------
// - 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, SvStream& rOStm, FilterConfigItem* pFilterConfigItem )
{
const sal_uLong nHeaderPos = rOStm.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;
mpStm = &rOStm;
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()
rOStm.SeekRel( 108 );
// write initial values
// set 100th mm map mode in EMF
ImplBeginRecord( WIN_EMR_SETMAPMODE );
(*mpStm) << (sal_Int32) MM_ANISOTROPIC;
ImplEndRecord();
ImplBeginRecord( WIN_EMR_SETVIEWPORTEXTEX );
(*mpStm) << (sal_Int32) maVDev.ImplGetDPIX() << (sal_Int32) maVDev.ImplGetDPIY();
ImplEndRecord();
ImplBeginRecord( WIN_EMR_SETWINDOWEXTEX );
(*mpStm) << (sal_Int32) 2540 << (sal_Int32) 2540;
ImplEndRecord();
ImplBeginRecord( WIN_EMR_SETVIEWPORTORGEX );
(*mpStm) << (sal_Int32) 0 << (sal_Int32) 0;
ImplEndRecord();
ImplBeginRecord( WIN_EMR_SETWINDOWORGEX );
(*mpStm) << (sal_Int32) 0 << (sal_Int32) 0;
ImplEndRecord();
ImplWriteRasterOp( ROP_OVERPAINT );
ImplBeginRecord( WIN_EMR_SETBKMODE );
(*mpStm) << (sal_uInt32) 1; // TRANSPARENT
ImplEndRecord();
// write emf data
ImplWrite( rMtf );
ImplBeginRecord( WIN_EMR_EOF );
(*mpStm)<< (sal_uInt32)0 // nPalEntries
<< (sal_uInt32)0x10 // offPalEntries
<< (sal_uInt32)0x14; // nSizeLast
ImplEndRecord();
// write header
const sal_uLong nEndPos = mpStm->Tell(); mpStm->Seek( nHeaderPos );
(*mpStm) << (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
mpStm->Seek( nEndPos );
delete[] mpHandlesUsed;
return( mpStm->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 = mpStm->Tell();
(*mpStm) << nType;
mpStm->SeekRel( 4 );
}
}
// -----------------------------------------------------------------------------
void EMFWriter::ImplEndRecord()
{
DBG_ASSERT( mbRecordOpen, "Record was not opened!" );
if( mbRecordOpen )
{
sal_Int32 nFillBytes, nActPos = mpStm->Tell();
mpStm->Seek( mnRecordPos + 4 );
nFillBytes = nActPos - mnRecordPos;
nFillBytes += 3; // each record has to be dword aligned
nFillBytes ^= 3;
nFillBytes &= 3;
*mpStm << (sal_uInt32)( ( nActPos - mnRecordPos ) + nFillBytes );
mpStm->Seek( nActPos );
while( nFillBytes-- )
*mpStm << (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 );
( *mpStm ) << nStockObject;
ImplEndRecord();
// destroy handle of created object
ImplBeginRecord( WIN_EMR_DELETEOBJECT );
( *mpStm ) << 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 );
(*mpStm) << mnLineHandle << nStyle << nWidth << nHeight;
ImplWriteColor( maVDev.GetLineColor() );
ImplEndRecord();
ImplBeginRecord( WIN_EMR_SELECTOBJECT );
(*mpStm) << 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 );
(*mpStm) << mnFillHandle << nStyle;
ImplWriteColor( maVDev.GetFillColor() );
(*mpStm) << nPatternStyle;
ImplEndRecord();
ImplBeginRecord( WIN_EMR_SELECTOBJECT );
(*mpStm) << 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 );
(*mpStm) << mnTextHandle;
ImplWriteExtent( -rFont.GetSize().Height() );
ImplWriteExtent( rFont.GetSize().Width() );
(*mpStm) << (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;
}
(*mpStm) << nWeight;
(*mpStm) << (sal_uInt8) ( ( ITALIC_NONE == rFont.GetItalic() ) ? 0 : 1 );
(*mpStm) << (sal_uInt8) ( ( UNDERLINE_NONE == rFont.GetUnderline() ) ? 0 : 1 );
(*mpStm) << (sal_uInt8) ( ( STRIKEOUT_NONE == rFont.GetStrikeout() ) ? 0 : 1 );
(*mpStm) << (sal_uInt8) ( ( RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet() ) ? 2 : 0 );
(*mpStm) << (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;
}
(*mpStm) << nPitchAndFamily;
for( i = 0; i < 32; i++ )
(*mpStm) << (sal_Unicode) ( ( i < aFontName.Len() ) ? aFontName.GetChar( i ) : 0 );
// dummy elfFullName
for( i = 0; i < 64; i++ )
(*mpStm) << (sal_Unicode) 0;
// dummy elfStyle
for( i = 0; i < 32; i++ )
(*mpStm) << (sal_Unicode) 0;
// dummy elfVersion, elfStyleSize, elfMatch, elfReserved
(*mpStm) << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 ;
// dummy elfVendorId
(*mpStm) << (sal_uInt32) 0;
// dummy elfCulture
(*mpStm) << (sal_uInt32) 0;
// dummy elfPanose
(*mpStm) << (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
(*mpStm) << (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 );
(*mpStm) << nTextAlign;
ImplEndRecord();
// Text color
ImplBeginRecord( WIN_EMR_SETTEXTCOLOR );
ImplWriteColor( maVDev.GetTextColor() );
ImplEndRecord();
ImplBeginRecord( WIN_EMR_SELECTOBJECT );
(*mpStm) << 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;
(*mpStm) << 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 );
(*mpStm) << nROP2;
ImplEndRecord();
}
// -----------------------------------------------------------------------------
void EMFWriter::ImplWriteExtent( long nExtent )
{
nExtent = maVDev.LogicToLogic( Size( nExtent, 0 ), maVDev.GetMapMode(), maDestMapMode ).Width();
(*mpStm) << (sal_Int32) nExtent;
}
// -----------------------------------------------------------------------------
void EMFWriter::ImplWritePoint( const Point& rPoint )
{
const Point aPoint( maVDev.LogicToLogic( rPoint, maVDev.GetMapMode(), maDestMapMode ));
(*mpStm) << (sal_Int32) aPoint.X() << (sal_Int32) aPoint.Y();
}
// -----------------------------------------------------------------------------
void EMFWriter::ImplWriteSize( const Size& rSize)
{
const Size aSize( maVDev.LogicToLogic( rSize, maVDev.GetMapMode(), maDestMapMode ));
(*mpStm) << (sal_Int32) aSize.Width() << (sal_Int32) aSize.Height();
}
// -----------------------------------------------------------------------------
void EMFWriter::ImplWriteRect( const Rectangle& rRect )
{
const Rectangle aRect( maVDev.LogicToLogic ( rRect, maVDev.GetMapMode(), maDestMapMode ));
(*mpStm) << 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() );
(*mpStm) << (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() );
(*mpStm) << (sal_uInt32)nPolyCount << nTotalPoints;
for( i = 0; i < nPolyCount; i++ )
(*mpStm) << (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() );
(*mpStm) << (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() );
(*mpStm) << (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 );
(*mpStm) << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) aBmpSizePixel.Width() << (sal_Int32) aBmpSizePixel.Height();
// write offset positions and sizes later
const sal_uLong nOffPos = mpStm->Tell();
mpStm->SeekRel( 16 );
(*mpStm) << (sal_uInt32) 0 << ( ( ROP_XOR == maVDev.GetRasterOp() && WIN_SRCCOPY == nROP ) ? WIN_SRCINVERT : nROP );
ImplWriteSize( rSz );
WriteDIB(rBmp, aMemStm, true, 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 );
mpStm->Write( aMemStm.GetData(), nDIBSize );
const sal_uLong nEndPos = mpStm->Tell();
mpStm->Seek( nOffPos );
(*mpStm) << (sal_uInt32) 80 << (sal_uInt32)( nHeaderSize + ( nPalCount << 2 ) );
(*mpStm) << (sal_uInt32)( 80 + ( nHeaderSize + ( nPalCount << 2 ) ) ) << nImageSize;
mpStm->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() ) ) );
(*mpStm) << (sal_uInt32)1;
(*mpStm) << (sal_Int32) 0 << (sal_Int32) 0;
ImplWritePoint( rPos );
(*mpStm) << (sal_uInt32) nLen << (sal_uInt32) 76 << (sal_uInt32) 2;
(*mpStm) << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) 0;
(*mpStm) << (sal_uInt32) ( 76 + ( nLen << 1 ) + ( (nLen & 1 ) ? 2 : 0 ) );
// write text
for( i = 0; i < nLen; i++ )
(*mpStm) << (sal_Unicode)rText.GetChar( i );
// padding word
if( nLen & 1 )
(*mpStm) << (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( sal_uLong j = 0, nActionCount = rMtf.GetActionCount(); 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( sal_uLong i = 0, nCount = aSubstitute.GetActionCount(); 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 );
(*mpStm) << (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 );
(*mpStm) << (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;
default:
DBG_ERROR( ( ByteString( "EMFWriter::ImplWriteActions: unsupported MetaAction #" ) += ByteString::CreateFromInt32( nType ) ).GetBuffer() );
break;
}
}
}