summaryrefslogtreecommitdiff
path: root/vcl/source/filter/wmf
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/filter/wmf')
-rw-r--r--vcl/source/filter/wmf/emfwr.cxx1412
-rw-r--r--vcl/source/filter/wmf/emfwr.hxx93
-rw-r--r--vcl/source/filter/wmf/enhwmf.cxx1418
-rw-r--r--vcl/source/filter/wmf/winmtf.cxx2239
-rw-r--r--vcl/source/filter/wmf/winmtf.hxx890
-rw-r--r--vcl/source/filter/wmf/winwmf.cxx1503
-rw-r--r--vcl/source/filter/wmf/wmf.cxx110
-rw-r--r--vcl/source/filter/wmf/wmfwr.cxx2052
-rw-r--r--vcl/source/filter/wmf/wmfwr.hxx220
9 files changed, 9937 insertions, 0 deletions
diff --git a/vcl/source/filter/wmf/emfwr.cxx b/vcl/source/filter/wmf/emfwr.cxx
new file mode 100644
index 000000000000..c4caf024b47f
--- /dev/null
+++ b/vcl/source/filter/wmf/emfwr.cxx
@@ -0,0 +1,1412 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include "emfwr.hxx"
+#include <rtl/strbuf.hxx>
+#include <tools/helpers.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <vcl/lineinfo.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, 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
+ << static_cast<sal_Int32>(aRect.Left())
+ << static_cast<sal_Int32>(aRect.Top())
+ << static_cast<sal_Int32>(aRect.Right())
+ << static_cast<sal_Int32>(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 << sal_Int32( ( 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( rtl::OUString(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;
+
+ default:
+ OSL_FAIL(rtl::OStringBuffer(RTL_CONSTASCII_STRINGPARAM(
+ "EMFWriter::ImplWriteActions: unsupported MetaAction #" )).
+ append(static_cast<sal_Int32>(nType)).getStr());
+ break;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/emfwr.hxx b/vcl/source/filter/wmf/emfwr.hxx
new file mode 100644
index 000000000000..f930c352ae33
--- /dev/null
+++ b/vcl/source/filter/wmf/emfwr.hxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#ifndef _EMFWR_HXX
+#define _EMFWR_HXX
+
+#include <vcl/metaact.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/virdev.hxx>
+#include <svtools/fltcall.hxx>
+
+// -------------
+// - EMFWriter -
+// -------------
+
+class LineInfo;
+namespace basegfx { class B2DPolygon; }
+
+class EMFWriter
+{
+private:
+
+ VirtualDevice maVDev;
+ MapMode maDestMapMode;
+ FilterConfigItem* mpFilterConfigItem;
+ SvStream& m_rStm;
+ sal_Bool* mpHandlesUsed;
+ sal_uLong mnHandleCount;
+ sal_uLong mnLastPercent;
+ sal_uLong mnRecordCount;
+ sal_uLong mnRecordPos;
+ sal_Bool mbRecordOpen;
+ sal_Bool mbLineChanged;
+ sal_uInt32 mnLineHandle;
+ sal_Bool mbFillChanged;
+ sal_uInt32 mnFillHandle;
+ sal_Bool mbTextChanged;
+ sal_uInt32 mnTextHandle;
+ sal_uInt32 mnHorTextAlign;
+
+ void ImplBeginRecord( sal_uInt32 nType );
+ void ImplEndRecord();
+
+ sal_uLong ImplAcquireHandle();
+ void ImplReleaseHandle( sal_uLong nHandle );
+
+ sal_Bool ImplPrepareHandleSelect( sal_uInt32& rHandle, sal_uLong nSelectType );
+ void ImplCheckLineAttr();
+ void ImplCheckFillAttr();
+ void ImplCheckTextAttr();
+
+ void ImplWriteColor( const Color& rColor );
+ void ImplWriteRasterOp( RasterOp eRop );
+ void ImplWriteExtent( long nExtent );
+ void ImplWritePoint( const Point& rPoint );
+ void ImplWriteSize( const Size& rSize);
+ void ImplWriteRect( const Rectangle& rRect );
+ void ImplWritePath( const PolyPolygon& rPolyPoly, sal_Bool bClose );
+ void ImplWritePolygonRecord( const Polygon& rPoly, sal_Bool bClose );
+ void ImplWritePolyPolygonRecord( const PolyPolygon& rPolyPoly );
+ void ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt, const Size& rSz, sal_uInt32 nROP );
+ void ImplWriteTextRecord( const Point& rPos, const String rText, const sal_Int32* pDXArray, sal_uInt32 nWidth );
+
+ void Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon);
+ void ImplWrite( const GDIMetaFile& rMtf );
+
+public:
+
+ EMFWriter(SvStream &rStream) : m_rStm(rStream) {}
+
+ sal_Bool WriteEMF( const GDIMetaFile& rMtf, FilterConfigItem* pConfigItem = NULL );
+};
+
+#endif // _EMFWR_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/enhwmf.cxx b/vcl/source/filter/wmf/enhwmf.cxx
new file mode 100644
index 000000000000..f8b98845be4e
--- /dev/null
+++ b/vcl/source/filter/wmf/enhwmf.cxx
@@ -0,0 +1,1418 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include "winmtf.hxx"
+#include <osl/endian.h>
+#include <boost/bind.hpp>
+
+using namespace std;
+//=========================== GDI-Array ===================================
+
+#define EMR_HEADER 1
+#define EMR_POLYBEZIER 2
+#define EMR_POLYGON 3
+#define EMR_POLYLINE 4
+#define EMR_POLYBEZIERTO 5
+#define EMR_POLYLINETO 6
+#define EMR_POLYPOLYLINE 7
+#define EMR_POLYPOLYGON 8
+#define EMR_SETWINDOWEXTEX 9
+#define EMR_SETWINDOWORGEX 10
+#define EMR_SETVIEWPORTEXTEX 11
+#define EMR_SETVIEWPORTORGEX 12
+#define EMR_SETBRUSHORGEX 13
+#define EMR_EOF 14
+#define EMR_SETPIXELV 15
+#define EMR_SETMAPPERFLAGS 16
+#define EMR_SETMAPMODE 17
+#define EMR_SETBKMODE 18
+#define EMR_SETPOLYFILLMODE 19
+#define EMR_SETROP2 20
+#define EMR_SETSTRETCHBLTMODE 21
+#define EMR_SETTEXTALIGN 22
+#define EMR_SETCOLORADJUSTMENT 23
+#define EMR_SETTEXTCOLOR 24
+#define EMR_SETBKCOLOR 25
+#define EMR_OFFSETCLIPRGN 26
+#define EMR_MOVETOEX 27
+#define EMR_SETMETARGN 28
+#define EMR_EXCLUDECLIPRECT 29
+#define EMR_INTERSECTCLIPRECT 30
+#define EMR_SCALEVIEWPORTEXTEX 31
+#define EMR_SCALEWINDOWEXTEX 32
+#define EMR_SAVEDC 33
+#define EMR_RESTOREDC 34
+#define EMR_SETWORLDTRANSFORM 35
+#define EMR_MODIFYWORLDTRANSFORM 36
+#define EMR_SELECTOBJECT 37
+#define EMR_CREATEPEN 38
+#define EMR_CREATEBRUSHINDIRECT 39
+#define EMR_DELETEOBJECT 40
+#define EMR_ANGLEARC 41
+#define EMR_ELLIPSE 42
+#define EMR_RECTANGLE 43
+#define EMR_ROUNDRECT 44
+#define EMR_ARC 45
+#define EMR_CHORD 46
+#define EMR_PIE 47
+#define EMR_SELECTPALETTE 48
+#define EMR_CREATEPALETTE 49
+#define EMR_SETPALETTEENTRIES 50
+#define EMR_RESIZEPALETTE 51
+#define EMR_REALIZEPALETTE 52
+#define EMR_EXTFLOODFILL 53
+#define EMR_LINETO 54
+#define EMR_ARCTO 55
+#define EMR_POLYDRAW 56
+#define EMR_SETARCDIRECTION 57
+#define EMR_SETMITERLIMIT 58
+#define EMR_BEGINPATH 59
+#define EMR_ENDPATH 60
+#define EMR_CLOSEFIGURE 61
+#define EMR_FILLPATH 62
+#define EMR_STROKEANDFILLPATH 63
+#define EMR_STROKEPATH 64
+#define EMR_FLATTENPATH 65
+#define EMR_WIDENPATH 66
+#define EMR_SELECTCLIPPATH 67
+#define EMR_ABORTPATH 68
+
+#define EMR_GDICOMMENT 70
+#define EMR_FILLRGN 71
+#define EMR_FRAMERGN 72
+#define EMR_INVERTRGN 73
+#define EMR_PAINTRGN 74
+#define EMR_EXTSELECTCLIPRGN 75
+#define EMR_BITBLT 76
+#define EMR_STRETCHBLT 77
+#define EMR_MASKBLT 78
+#define EMR_PLGBLT 79
+#define EMR_SETDIBITSTODEVICE 80
+#define EMR_STRETCHDIBITS 81
+#define EMR_EXTCREATEFONTINDIRECTW 82
+#define EMR_EXTTEXTOUTA 83
+#define EMR_EXTTEXTOUTW 84
+#define EMR_POLYBEZIER16 85
+#define EMR_POLYGON16 86
+#define EMR_POLYLINE16 87
+#define EMR_POLYBEZIERTO16 88
+#define EMR_POLYLINETO16 89
+#define EMR_POLYPOLYLINE16 90
+#define EMR_POLYPOLYGON16 91
+#define EMR_POLYDRAW16 92
+#define EMR_CREATEMONOBRUSH 93
+#define EMR_CREATEDIBPATTERNBRUSHPT 94
+#define EMR_EXTCREATEPEN 95
+#define EMR_POLYTEXTOUTA 96
+#define EMR_POLYTEXTOUTW 97
+
+// WINDOWS VERSION >= 0x400
+#define EMR_SETICMMODE 98
+#define EMR_CREATECOLORSPACE 99
+#define EMR_SETCOLORSPACE 100
+#define EMR_DELETECOLORSPACE 101
+#define EMR_GLSRECORD 102
+#define EMR_GLSBOUNDEDRECORD 103
+#define EMR_PIXELFORMAT 104
+
+// WINDOWS VERSION >= 0x500
+#define EMR_DRAWESCAPE 105
+#define EMR_EXTESCAPE 106
+#define EMR_STARTDOC 107
+#define EMR_SMALLTEXTOUT 108
+#define EMR_FORCEUFIMAPPING 109
+#define EMR_NAMEDESCAPE 110
+#define EMR_COLORCORRECTPALETTE 111
+#define EMR_SETICMPROFILEA 112
+#define EMR_SETICMPROFILEW 113
+#define EMR_ALPHABLEND 114
+#define EMR_ALPHADIBBLEND 115
+#define EMR_TRANSPARENTBLT 116
+#define EMR_TRANSPARENTDIB 117
+#define EMR_GRADIENTFILL 118
+#define EMR_SETLINKEDUFIS 119
+#define EMR_SETTEXTJUSTIFICATION 120
+
+#if OSL_DEBUG_LEVEL > 1
+#define EMFP_DEBUG(x) x
+#else
+#define EMFP_DEBUG(x)
+#endif
+
+//-----------------------------------------------------------------------------------
+
+#ifdef OSL_BIGENDIAN
+// currently unused
+static float GetSwapFloat( SvStream& rSt )
+{
+ float fTmp;
+ sal_Int8* pPtr = (sal_Int8*)&fTmp;
+ rSt >> pPtr[3] >> pPtr[2] >> pPtr[1] >> pPtr[0]; // Little Endian <-> Big Endian switch
+ return fTmp;
+}
+#endif
+
+SvStream& operator>>( SvStream& rIn, XForm& rXForm )
+{
+ if ( sizeof( float ) != 4 )
+ {
+ OSL_FAIL( "EnhWMFReader::sizeof( float ) != 4" );
+ rXForm = XForm();
+ }
+ else
+ {
+#ifdef OSL_BIGENDIAN
+ rXForm.eM11 = GetSwapFloat( rIn );
+ rXForm.eM12 = GetSwapFloat( rIn );
+ rXForm.eM21 = GetSwapFloat( rIn );
+ rXForm.eM22 = GetSwapFloat( rIn );
+ rXForm.eDx = GetSwapFloat( rIn );
+ rXForm.eDy = GetSwapFloat( rIn );
+#else
+ rIn >> rXForm.eM11 >> rXForm.eM12 >> rXForm.eM21 >> rXForm.eM22
+ >> rXForm.eDx >> rXForm.eDy;
+#endif
+ }
+ return rIn;
+}
+
+static sal_Bool ImplReadRegion( PolyPolygon& rPolyPoly, SvStream& rSt, sal_uInt32 nLen )
+{
+ sal_Bool bOk = sal_False;
+ if ( nLen )
+ {
+ sal_uInt32 nHdSize, nType, nCount, nRgnSize, i;
+ rSt >> nHdSize
+ >> nType
+ >> nCount
+ >> nRgnSize;
+
+ if ( nCount && ( nType == RDH_RECTANGLES ) &&
+ ( nLen >= ( ( nCount << 4 ) + ( nHdSize - 16 ) ) ) )
+ {
+ sal_Int32 nx1, ny1, nx2, ny2;
+
+ for ( i = 0; i < nCount; i++ )
+ {
+ rSt >> nx1 >> ny1 >> nx2 >> ny2;
+
+ Rectangle aRect( Point( nx1, ny1 ), Point( nx2, ny2 ) );
+ Polygon aPolygon( aRect );
+ PolyPolygon aPolyPolyOr1( aPolygon );
+ PolyPolygon aPolyPolyOr2( rPolyPoly );
+ rPolyPoly.GetUnion( aPolyPolyOr1, aPolyPolyOr2 );
+ rPolyPoly = aPolyPolyOr2;
+ }
+ bOk = sal_True;
+ }
+ }
+ return bOk;
+}
+
+EMFP_DEBUG(void dumpWords( SvStream& s, int i )
+{
+ sal_uInt32 pos = s.Tell();
+ sal_Int16 data;
+ for( ; i > 0; i -- ) {
+ s >> data;
+ EMFP_DEBUG(printf ("\t\t\tdata: %04hx\n", data));
+ }
+ s.Seek (pos);
+});
+
+void EnhWMFReader::ReadEMFPlusComment(sal_uInt32 length, sal_Bool& bHaveDC)
+{
+ if (!bEMFPlus) {
+ pOut->PassEMFPlusHeaderInfo();
+
+ // debug code - write the stream to debug file /tmp/emf-stream.emf
+ EMFP_DEBUG(int pos = pWMF->Tell();
+ pWMF->Seek(0);
+ SvFileStream file( rtl::OUString( "/tmp/emf-stream.emf" ), STREAM_WRITE | STREAM_TRUNC );
+
+ *pWMF >> file;
+ file.Flush();
+ file.Close();
+
+ pWMF->Seek( pos );)
+ }
+ bEMFPlus = true;
+
+ sal_Size pos = pWMF->Tell();
+ void *buffer = malloc( length );
+ pOut->PassEMFPlus( buffer, pWMF->Read( buffer, length ) );
+ free( buffer );
+ pWMF->Seek( pos );
+
+ bHaveDC = false;
+
+ OSL_ASSERT(length >= 4);
+ //reduce by 32bit length itself, skip in SeekRel if
+ //impossibly unavailble
+ sal_uInt32 nRemainder = length >= 4 ? length-4 : length;
+
+ const size_t nRequiredHeaderSize = 12;
+ while (nRemainder >= nRequiredHeaderSize)
+ {
+ sal_uInt16 type(0), flags(0);
+ sal_uInt32 size(0), dataSize(0);
+
+ *pWMF >> type >> flags >> size >> dataSize;
+ nRemainder -= nRequiredHeaderSize;
+
+ EMFP_DEBUG(printf ("\t\tEMF+ record type: %d\n", type));
+
+ // GetDC
+ if( type == 16388 ) {
+ bHaveDC = true;
+ EMFP_DEBUG(printf ("\t\tEMF+ lock DC (device context)\n"));
+ }
+
+ //Get the length of the remaining data of this record based
+ //on the alleged size
+ sal_uInt32 nRemainingRecordData = size >= nRequiredHeaderSize ?
+ size-nRequiredHeaderSize : 0;
+ //clip to available size
+ nRemainingRecordData = std::min(nRemainingRecordData, nRemainder);
+ pWMF->SeekRel(nRemainingRecordData);
+ nRemainder -= nRemainingRecordData;
+ }
+ pWMF->SeekRel(nRemainder);
+}
+
+/**
+ * Reads polygons from the stream.
+ * The <class T> parameter is for the type of the points (sal_uInt32 or sal_uInt16).
+ * The <class Drawer> parameter is a boost binding for the method that will draw the polygon.
+ * skipFirst: if the first point read is the 0th point or the 1st point in the array.
+ * */
+template <class T, class Drawer>
+void EnhWMFReader::ReadAndDrawPolygon(Drawer drawer, const sal_Bool skipFirst)
+{
+ sal_uInt32 nPoints(0), nStartIndex(0);
+ pWMF->SeekRel( 16 );
+ *pWMF >> nPoints;
+ if (skipFirst)
+ {
+ nPoints ++;
+ nStartIndex ++;
+ }
+
+ Polygon aPolygon = ReadPolygon<T>(nStartIndex, nPoints);
+ drawer(pOut, aPolygon, skipFirst, bRecordPath);
+}
+
+
+/**
+ * Reads polygons from the stream.
+ * The <class T> parameter is for the type of the points
+ * nStartIndex: which is the starting index in the polygon of the first point read
+ * nPoints: number of points
+ * pWMF: the stream containings the polygons
+ * */
+template <class T>
+Polygon EnhWMFReader::ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints)
+{
+ Polygon aPolygon(nPoints);
+ for (sal_uInt16 i = nStartIndex ; i < nPoints && pWMF->good(); i++ )
+ {
+ T nX, nY;
+ *pWMF >> nX >> nY;
+ if (!pWMF->good())
+ break;
+ aPolygon[ i ] = Point( nX, nY );
+ }
+
+ return aPolygon;
+}
+
+/**
+ * Reads a polyline from the WMF file and draws it
+ * The <class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
+ * */
+template <class T>
+void EnhWMFReader::ReadAndDrawPolyLine()
+{
+ sal_uInt32 nPoints;
+ sal_Int32 i, nPoly(0), nGesPoints(0);
+ pWMF->SeekRel( 0x10 );
+ // Number of Polygons:
+ *pWMF >> nPoly >> nGesPoints;
+
+ // taking the amount of points of each polygon, retrieving the total number of points
+ if ( pWMF->good() &&
+ ( static_cast< sal_uInt32 >(nPoly) < SAL_MAX_UINT32 / sizeof(sal_uInt16) ) &&
+ ( static_cast< sal_uInt32 >( nPoly ) * sizeof(sal_uInt16) ) <= ( nEndPos - pWMF->Tell() )
+ )
+ {
+ sal_uInt16* pnPoints = new sal_uInt16[ nPoly ];
+ for ( i = 0; i < nPoly && pWMF->good(); i++ )
+ {
+ *pWMF >> nPoints;
+ pnPoints[ i ] = (sal_uInt16)nPoints;
+ }
+ // Get polygon points:
+ for ( i = 0; ( i < nPoly ) && pWMF->good(); i++ )
+ {
+ Polygon aPolygon = ReadPolygon<T>(0, pnPoints[i]);
+ pOut->DrawPolyLine( aPolygon, sal_False, bRecordPath );
+ }
+ delete[] pnPoints;
+ }
+}
+
+/**
+ * Reads a poly polygon from the WMF file and draws it.
+ * The <class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
+ * */
+template <class T>
+void EnhWMFReader::ReadAndDrawPolyPolygon()
+{
+ sal_uInt32 i, nPoly, nGesPoints, nPoints;
+ pWMF->SeekRel( 0x10 );
+ // Number of polygons
+ *pWMF >> nPoly >> nGesPoints;
+ if ( pWMF->good() &&
+ ( nGesPoints < SAL_MAX_UINT32 / sizeof(Point) ) && //check against numeric overflowing
+ ( nPoly < SAL_MAX_UINT32 / sizeof(sal_uInt16) ) &&
+ ( ( nPoly * sizeof( sal_uInt16 ) ) <= ( nEndPos - pWMF->Tell() ) ))
+ {
+ //Get number of points in each polygon
+ sal_uInt16 * pnPoints = new sal_uInt16[ nPoly ];
+ for ( i = 0; i < nPoly && pWMF->good(); i++ )
+ {
+ *pWMF >> nPoints;
+ pnPoints[ i ] = (sal_uInt16)nPoints;
+ } //end for
+ if ( pWMF->good() && ( nGesPoints * (sizeof(T)+sizeof(T)) ) <= ( nEndPos - pWMF->Tell() ) )
+ {
+ // Get polygon points
+ Point * pPtAry = new Point[ nGesPoints ];
+ for ( i = 0; i < nGesPoints && pWMF->good(); i++ )
+ {
+ T nX, nY;
+ *pWMF >> nX >> nY;
+ pPtAry[ i ] = Point( nX, nY );
+ } //end for
+ // Create PolyPolygon Actions
+ PolyPolygon aPolyPoly( (sal_uInt16)nPoly, pnPoints, pPtAry );
+ pOut->DrawPolyPolygon( aPolyPoly, bRecordPath );
+ delete[] pPtAry;
+ } //end if
+ delete[] pnPoints;
+ } //end if
+}
+
+sal_Bool EnhWMFReader::ReadEnhWMF()
+{
+ sal_uInt32 nStretchBltMode = 0;
+ sal_uInt32 nRecType(0), nRecSize(0), nNextPos(0),
+ nW(0), nH(0), nColor(0), nIndex(0),
+ nDat32(0), nNom1(0), nDen1(0), nNom2(0), nDen2(0);
+ sal_Int32 nX32(0), nY32(0), nx32(0), ny32(0);
+
+ sal_Bool bFlag(sal_False), bStatus = ReadHeader();
+ sal_Bool bHaveDC = false;
+
+ static sal_Bool bEnableEMFPlus = ( getenv( "EMF_PLUS_DISABLE" ) == NULL );
+
+ while( bStatus && nRecordCount-- && pWMF->good())
+ {
+ *pWMF >> nRecType >> nRecSize;
+
+ if ( !pWMF->good() || ( nRecSize < 8 ) || ( nRecSize & 3 ) ) // Parameters are always divisible by 4
+ {
+ bStatus = sal_False;
+ break;
+ }
+
+ nNextPos = pWMF->Tell() + ( nRecSize - 8 );
+
+ if ( !pWMF->good() || nNextPos > nEndPos )
+ {
+ bStatus = sal_False;
+ break;
+ }
+
+ if( !aBmpSaveList.empty()
+ && ( nRecType != EMR_STRETCHBLT )
+ && ( nRecType != EMR_STRETCHDIBITS )
+ )
+ pOut->ResolveBitmapActions( aBmpSaveList );
+
+ bFlag = sal_False;
+
+ EMFP_DEBUG(printf ("0x%04x-0x%04x record type: %d size: %d\n",(unsigned int) (nNextPos - nRecSize),(unsigned int) nNextPos, (int)nRecType,(int) nRecSize));
+
+ if( bEnableEMFPlus && nRecType == EMR_GDICOMMENT ) {
+ sal_uInt32 length;
+
+ *pWMF >> length;
+
+ EMFP_DEBUG(printf ("\tGDI comment\n\t\tlength: %d\n", (int)length));
+
+ if( pWMF->good() && length >= 4 ) {
+ sal_uInt32 id;
+
+ *pWMF >> id;
+
+ EMFP_DEBUG(printf ("\t\tbegin %c%c%c%c id: 0x%x\n", (char)(id & 0xff), (char)((id & 0xff00) >> 8), (char)((id & 0xff0000) >> 16), (char)((id & 0xff000000) >> 24), (unsigned int)id));
+
+ // EMF+ comment (fixme: BE?)
+ if( id == 0x2B464D45 && nRecSize >= 12 )
+ ReadEMFPlusComment( length, bHaveDC );
+ // GDIC comment, doesn't do anything useful yet
+ else if( id == 0x43494447 && nRecSize >= 12 ) {
+ //ToDo: ReadGDIComment()
+ } else {
+ EMFP_DEBUG(printf ("\t\tunknown id: 0x%x\n",(unsigned int) id));
+ }
+ }
+ } else if( !bEMFPlus || bHaveDC || nRecType == EMR_EOF )
+
+ switch( nRecType )
+ {
+ case EMR_POLYBEZIERTO :
+ ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_True);
+ break;
+ case EMR_POLYBEZIER :
+ ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYGON :
+ ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolygon, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYLINETO :
+ ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_True);
+ break;
+ case EMR_POLYLINE :
+ ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYPOLYLINE :
+ ReadAndDrawPolyLine<sal_Int32>();
+ break;
+
+ case EMR_POLYPOLYGON :
+ ReadAndDrawPolyPolygon<sal_Int32>();
+ break;
+
+ case EMR_SETWINDOWEXTEX :
+ { // #75383#
+ *pWMF >> nW >> nH;
+ pOut->SetWinExt( Size( nW, nH ) );
+ }
+ break;
+
+ case EMR_SETWINDOWORGEX :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->SetWinOrg( Point( nX32, nY32 ) );
+ }
+ break;
+
+ case EMR_SCALEWINDOWEXTEX :
+ {
+ *pWMF >> nNom1 >> nDen1 >> nNom2 >> nDen2;
+ pOut->ScaleWinExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
+ }
+ break;
+
+ case EMR_SETVIEWPORTORGEX :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->SetDevOrg( Point( nX32, nY32 ) );
+ }
+ break;
+
+ case EMR_SCALEVIEWPORTEXTEX :
+ {
+ *pWMF >> nNom1 >> nDen1 >> nNom2 >> nDen2;
+ pOut->ScaleDevExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
+ }
+ break;
+
+ case EMR_SETVIEWPORTEXTEX :
+ {
+ *pWMF >> nW >> nH;
+ pOut->SetDevExt( Size( nW, nH ) );
+ }
+ break;
+
+ case EMR_EOF :
+ nRecordCount = 0; // #76846#
+ break;
+
+ case EMR_SETPIXELV :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->DrawPixel( Point( nX32, nY32 ), ReadColor() );
+ }
+ break;
+
+ case EMR_SETMAPMODE :
+ {
+ sal_uInt32 nMapMode;
+ *pWMF >> nMapMode;
+ pOut->SetMapMode( nMapMode );
+ }
+ break;
+
+ case EMR_SETBKMODE :
+ {
+ *pWMF >> nDat32;
+ pOut->SetBkMode( nDat32 );
+ }
+ break;
+
+ case EMR_SETPOLYFILLMODE :
+ break;
+
+ case EMR_SETROP2 :
+ {
+ *pWMF >> nDat32;
+ pOut->SetRasterOp( nDat32 );
+ }
+ break;
+
+ case EMR_SETSTRETCHBLTMODE :
+ {
+ *pWMF >> nStretchBltMode;
+ }
+ break;
+
+ case EMR_SETTEXTALIGN :
+ {
+ *pWMF >> nDat32;
+ pOut->SetTextAlign( nDat32 );
+ }
+ break;
+
+ case EMR_SETTEXTCOLOR :
+ {
+ pOut->SetTextColor( ReadColor() );
+ }
+ break;
+
+ case EMR_SETBKCOLOR :
+ {
+ pOut->SetBkColor( ReadColor() );
+ }
+ break;
+
+ case EMR_OFFSETCLIPRGN :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->MoveClipRegion( Size( nX32, nY32 ) );
+ }
+ break;
+
+ case EMR_MOVETOEX :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->MoveTo( Point( nX32, nY32 ), bRecordPath );
+ }
+ break;
+
+ case EMR_INTERSECTCLIPRECT :
+ {
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
+ pOut->IntersectClipRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+ }
+ break;
+
+ case EMR_SAVEDC :
+ {
+ pOut->Push();
+ }
+ break;
+
+ case EMR_RESTOREDC :
+ {
+ pOut->Pop();
+ }
+ break;
+
+ case EMR_SETWORLDTRANSFORM :
+ {
+ XForm aTempXForm;
+ *pWMF >> aTempXForm;
+ pOut->SetWorldTransform( aTempXForm );
+ }
+ break;
+
+ case EMR_MODIFYWORLDTRANSFORM :
+ {
+ sal_uInt32 nMode;
+ XForm aTempXForm;
+ *pWMF >> aTempXForm >> nMode;
+ pOut->ModifyWorldTransform( aTempXForm, nMode );
+ }
+ break;
+
+ case EMR_SELECTOBJECT :
+ {
+ *pWMF >> nIndex;
+ pOut->SelectObject( nIndex );
+ }
+ break;
+
+ case EMR_CREATEPEN :
+ {
+ *pWMF >> nIndex;
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+
+ LineInfo aLineInfo;
+ sal_uInt32 nStyle;
+ Size aSize;
+ //#fdo39428 Remove SvStream operator>>(long&)
+ sal_Int32 nTmpW(0), nTmpH(0);
+
+ *pWMF >> nStyle >> nTmpW >> nTmpH;
+ aSize.Width() = nTmpW;
+ aSize.Height() = nTmpH;
+
+ if ( aSize.Width() )
+ aLineInfo.SetWidth( aSize.Width() );
+
+ sal_Bool bTransparent = sal_False;
+ sal_uInt16 nDashCount = 0;
+ sal_uInt16 nDotCount = 0;
+ switch( nStyle )
+ {
+ case PS_DASHDOTDOT :
+ nDotCount++;
+ case PS_DASHDOT :
+ nDashCount++;
+ case PS_DOT :
+ nDotCount++;
+ break;
+ case PS_DASH :
+ nDashCount++;
+ break;
+ case PS_NULL :
+ bTransparent = sal_True;
+ aLineInfo.SetStyle( LINE_NONE );
+ break;
+ default :
+ case PS_INSIDEFRAME :
+ case PS_SOLID :
+ aLineInfo.SetStyle( LINE_SOLID );
+ }
+ if ( nDashCount | nDotCount )
+ {
+ aLineInfo.SetStyle( LINE_DASH );
+ aLineInfo.SetDashCount( nDashCount );
+ aLineInfo.SetDotCount( nDotCount );
+ }
+ pOut->CreateObject( nIndex, GDI_PEN, new WinMtfLineStyle( ReadColor(), aLineInfo, bTransparent ) );
+ }
+ }
+ break;
+
+ case EMR_EXTCREATEPEN :
+ {
+ sal_Int32 elpHatch;
+ sal_uInt32 offBmi, cbBmi, offBits, cbBits, nStyle, nWidth, nBrushStyle, elpNumEntries;
+ Color aColorRef;
+
+ *pWMF >> nIndex;
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ *pWMF >> offBmi >> cbBmi >> offBits >> cbBits >> nStyle >> nWidth >> nBrushStyle;
+ aColorRef = ReadColor();
+ *pWMF >> elpHatch >> elpNumEntries;
+
+ LineInfo aLineInfo;
+ if ( nWidth )
+ aLineInfo.SetWidth( nWidth );
+
+ sal_Bool bTransparent = sal_False;
+ sal_uInt16 nDashCount = 0;
+ sal_uInt16 nDotCount = 0;
+
+ switch( nStyle & PS_STYLE_MASK )
+ {
+ case PS_DASHDOTDOT :
+ nDotCount++;
+ case PS_DASHDOT :
+ nDashCount++;
+ case PS_DOT :
+ nDotCount++;
+ break;
+ case PS_DASH :
+ nDashCount++;
+ break;
+ case PS_NULL :
+ bTransparent = sal_True;
+ aLineInfo.SetStyle( LINE_NONE );
+ break;
+
+ default :
+ case PS_INSIDEFRAME :
+ case PS_SOLID :
+ aLineInfo.SetStyle( LINE_SOLID );
+ }
+ if ( nDashCount | nDotCount )
+ {
+ aLineInfo.SetStyle( LINE_DASH );
+ aLineInfo.SetDashCount( nDashCount );
+ aLineInfo.SetDotCount( nDotCount );
+ }
+ pOut->CreateObject( nIndex, GDI_PEN, new WinMtfLineStyle( aColorRef, aLineInfo, bTransparent ) );
+ }
+ }
+ break;
+
+ case EMR_CREATEBRUSHINDIRECT :
+ {
+ sal_uInt32 nStyle;
+ *pWMF >> nIndex;
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ *pWMF >> nStyle;
+ pOut->CreateObject( nIndex, GDI_BRUSH, new WinMtfFillStyle( ReadColor(), ( nStyle == BS_HOLLOW ) ? sal_True : sal_False ) );
+ }
+ }
+ break;
+
+ case EMR_DELETEOBJECT :
+ {
+ *pWMF >> nIndex;
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ pOut->DeleteObject( nIndex );
+ }
+ break;
+
+ case EMR_ELLIPSE :
+ {
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
+ pOut->DrawEllipse( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+ }
+ break;
+
+ case EMR_RECTANGLE :
+ {
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
+ pOut->DrawRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+ }
+ break;
+
+ case EMR_ROUNDRECT :
+ {
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nW >> nH;
+ Size aSize( Size( nW, nH ) );
+ pOut->DrawRoundRect( ReadRectangle( nX32, nY32, nx32, ny32 ), aSize );
+ }
+ break;
+
+ case EMR_ARC :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
+ pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+ }
+ break;
+
+ case EMR_CHORD :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
+ pOut->DrawChord( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+ }
+ break;
+
+ case EMR_PIE :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
+ const Rectangle aRect( ReadRectangle( nX32, nY32, nx32, ny32 ));
+
+ // #i73608# OutputDevice deviates from WMF
+ // semantics. start==end means full ellipse here.
+ if( nStartX == nEndX && nStartY == nEndY )
+ pOut->DrawEllipse( aRect );
+ else
+ pOut->DrawPie( aRect, Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+ }
+ break;
+
+ case EMR_LINETO :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->LineTo( Point( nX32, nY32 ), bRecordPath );
+ }
+ break;
+
+ case EMR_ARCTO :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
+ pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ), sal_True );
+ }
+ break;
+
+ case EMR_BEGINPATH :
+ {
+ pOut->ClearPath();
+ bRecordPath = sal_True;
+ }
+ break;
+
+ case EMR_ABORTPATH :
+ pOut->ClearPath();
+ case EMR_ENDPATH :
+ bRecordPath = sal_False;
+ break;
+
+ case EMR_CLOSEFIGURE :
+ pOut->ClosePath();
+ break;
+
+ case EMR_FILLPATH :
+ pOut->StrokeAndFillPath( sal_False, sal_True );
+ break;
+
+ case EMR_STROKEANDFILLPATH :
+ pOut->StrokeAndFillPath( sal_True, sal_True );
+ break;
+
+ case EMR_STROKEPATH :
+ pOut->StrokeAndFillPath( sal_True, sal_False );
+ break;
+
+ case EMR_SELECTCLIPPATH :
+ {
+ sal_Int32 nClippingMode;
+ *pWMF >> nClippingMode;
+ pOut->SetClipPath( pOut->GetPathObj(), nClippingMode, sal_True );
+ }
+ break;
+
+ case EMR_EXTSELECTCLIPRGN :
+ {
+ sal_Int32 iMode, cbRgnData;
+ *pWMF >> cbRgnData
+ >> iMode;
+
+ PolyPolygon aPolyPoly;
+ if ( cbRgnData )
+ ImplReadRegion( aPolyPoly, *pWMF, nRecSize );
+ pOut->SetClipPath( aPolyPoly, iMode, sal_False );
+ }
+ break;
+
+ case EMR_BITBLT : // PASSTHROUGH INTENDED
+ case EMR_STRETCHBLT :
+ {
+ sal_Int32 xDest, yDest, cxDest, cyDest, xSrc, ySrc, cxSrc, cySrc;
+ sal_uInt32 dwRop, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc;
+ XForm xformSrc;
+
+ sal_uInt32 nStart = pWMF->Tell() - 8;
+
+ pWMF->SeekRel( 0x10 );
+ *pWMF >> xDest >> yDest >> cxDest >> cyDest >> dwRop >> xSrc >> ySrc
+ >> xformSrc >> nColor >> iUsageSrc >> offBmiSrc >> cbBmiSrc
+ >> offBitsSrc >> cbBitsSrc;
+
+ if ( nRecType == EMR_STRETCHBLT )
+ *pWMF >> cxSrc >> cySrc;
+ else
+ cxSrc = cySrc = 0;
+
+ Bitmap aBitmap;
+ Rectangle aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
+
+ cxDest = abs( (int)cxDest ); // sj: i37894, size can be negative
+ cyDest = abs( (int)cyDest ); // and also 122889
+
+ if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
+ bStatus = sal_False;
+ else
+ {
+ sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
+ if ( nSize <= ( nEndPos - nStartPos ) )
+ {
+ char* pBuf = new char[ nSize ];
+ SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
+ aTmp.ObjectOwnsMemory( sal_True );
+ aTmp << (sal_uInt8)'B'
+ << (sal_uInt8)'M'
+ << (sal_uInt32)cbBitsSrc
+ << (sal_uInt16)0
+ << (sal_uInt16)0
+ << (sal_uInt32)cbBmiSrc + 14;
+ pWMF->Seek( nStart + offBmiSrc );
+ pWMF->Read( pBuf + 14, cbBmiSrc );
+ pWMF->Seek( nStart + offBitsSrc );
+ pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
+ aTmp.Seek( 0 );
+ aBitmap.Read( aTmp, sal_True );
+
+ // test if it is sensible to crop
+ if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
+ ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
+ ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
+ ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
+ {
+ Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
+ aBitmap.Crop( aCropRect );
+ }
+ aBmpSaveList.push_back( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ) );
+ }
+ }
+ }
+ break;
+
+ case EMR_STRETCHDIBITS :
+ {
+ sal_Int32 xDest, yDest, xSrc, ySrc, cxSrc, cySrc, cxDest, cyDest;
+ sal_uInt32 offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, iUsageSrc, dwRop;
+ sal_uInt32 nStart = pWMF->Tell() - 8;
+
+ pWMF->SeekRel( 0x10 );
+ *pWMF >> xDest
+ >> yDest
+ >> xSrc
+ >> ySrc
+ >> cxSrc
+ >> cySrc
+ >> offBmiSrc
+ >> cbBmiSrc
+ >> offBitsSrc
+ >> cbBitsSrc
+ >> iUsageSrc
+ >> dwRop
+ >> cxDest
+ >> cyDest;
+
+ Bitmap aBitmap;
+ Rectangle aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
+
+ cxDest = abs( (int)cxDest ); // sj: i37894, size can be negative
+ cyDest = abs( (int)cyDest ); // and also 122889
+
+ if ( ((SAL_MAX_UINT32 - 14) < cbBitsSrc)
+ || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc )
+ )
+ {
+ bStatus = sal_False;
+ }
+ else
+ {
+ sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
+ if ( nSize <= ( nEndPos - nStartPos ) )
+ {
+ char* pBuf = new char[ nSize ];
+ SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
+ aTmp.ObjectOwnsMemory( sal_True );
+ aTmp << (sal_uInt8)'B'
+ << (sal_uInt8)'M'
+ << (sal_uInt32)cbBitsSrc
+ << (sal_uInt16)0
+ << (sal_uInt16)0
+ << (sal_uInt32)cbBmiSrc + 14;
+ pWMF->Seek( nStart + offBmiSrc );
+ pWMF->Read( pBuf + 14, cbBmiSrc );
+ pWMF->Seek( nStart + offBitsSrc );
+ pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
+ aTmp.Seek( 0 );
+ aBitmap.Read( aTmp, sal_True );
+
+ // test if it is sensible to crop
+ if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
+ ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
+ ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
+ ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
+ {
+ Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
+ aBitmap.Crop( aCropRect );
+ }
+ aBmpSaveList.push_back( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ) );
+ }
+ }
+ }
+ break;
+
+ case EMR_EXTCREATEFONTINDIRECTW :
+ {
+ *pWMF >> nIndex;
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ LOGFONTW aLogFont;
+ *pWMF >> aLogFont.lfHeight
+ >> aLogFont.lfWidth
+ >> aLogFont.lfEscapement
+ >> aLogFont.lfOrientation
+ >> aLogFont.lfWeight
+ >> aLogFont.lfItalic
+ >> aLogFont.lfUnderline
+ >> aLogFont.lfStrikeOut
+ >> aLogFont.lfCharSet
+ >> aLogFont.lfOutPrecision
+ >> aLogFont.lfClipPrecision
+ >> aLogFont.lfQuality
+ >> aLogFont.lfPitchAndFamily;
+
+ sal_Unicode lfFaceName[ LF_FACESIZE ];
+
+ for ( int i = 0; i < LF_FACESIZE; i++ )
+ {
+ sal_uInt16 nChar;
+ *pWMF >> nChar;
+ lfFaceName[ i ] = nChar;
+ }
+ aLogFont.alfFaceName = rtl::OUString( lfFaceName );
+ pOut->CreateObject( nIndex, GDI_FONT, new WinMtfFontStyle( aLogFont ) );
+ }
+ }
+ break;
+
+ case EMR_EXTTEXTOUTA :
+ bFlag = sal_True;
+ case EMR_EXTTEXTOUTW :
+ {
+ sal_Int32 nLeft, nTop, nRight, nBottom, ptlReferenceX, ptlReferenceY, nGfxMode, nXScale, nYScale;
+ sal_uInt32 nCurPos, nLen, nOffString, nOptions, offDx;
+ sal_Int32* pDX = NULL;
+
+ nCurPos = pWMF->Tell() - 8;
+
+ *pWMF >> nLeft >> nTop >> nRight >> nBottom >> nGfxMode >> nXScale >> nYScale
+ >> ptlReferenceX >> ptlReferenceY >> nLen >> nOffString >> nOptions;
+
+ pWMF->SeekRel( 0x10 );
+ *pWMF >> offDx;
+
+ sal_Int32 nTextLayoutMode = TEXT_LAYOUT_DEFAULT;
+ if ( nOptions & ETO_RTLREADING )
+ nTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
+ pOut->SetTextLayoutMode( nTextLayoutMode );
+ DBG_ASSERT( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
+
+ Point aPos( ptlReferenceX, ptlReferenceY );
+ if ( nLen && ( nLen < SAL_MAX_UINT32 / sizeof(sal_Int32) ) )
+ {
+ if ( offDx && (( nCurPos + offDx + nLen * 4 ) <= nNextPos ) )
+ {
+ pWMF->Seek( nCurPos + offDx );
+ if ( ( nLen * sizeof(sal_uInt32) ) <= ( nEndPos - pWMF->Tell() ) )
+ {
+ pDX = new sal_Int32[ nLen ];
+ sal_uInt32 i;
+ for ( i = 0; i < nLen; i++ )
+ *pWMF >> pDX[ i ];
+ }
+ }
+ pWMF->Seek( nCurPos + nOffString );
+ String aText;
+ if ( bFlag )
+ {
+ if ( nLen <= ( nEndPos - pWMF->Tell() ) )
+ {
+ sal_Char* pBuf = new sal_Char[ nLen ];
+ pWMF->Read( pBuf, nLen );
+ aText = String( pBuf, (sal_uInt16)nLen, pOut->GetCharSet() );
+ delete[] pBuf;
+
+ if ( aText.Len() != nLen )
+ {
+ sal_uInt16 i, j;
+ sal_Int32* pOldDx = pDX;
+ pDX = new sal_Int32[ aText.Len() ];
+ for ( i = 0, j = 0; i < aText.Len(); i++ )
+ {
+ sal_Unicode cUniChar = aText.GetChar(i);
+ rtl::OString aCharacter(&cUniChar, 1, pOut->GetCharSet());
+ pDX[ i ] = 0;
+ for (sal_Int32 k = 0; ( k < aCharacter.getLength() ) && ( j < nLen ) && ( i < aText.Len() ); ++k)
+ pDX[ i ] += pOldDx[ j++ ];
+ }
+ delete[] pOldDx;
+ }
+ }
+ }
+ else
+ {
+ if ( ( nLen * sizeof(sal_Unicode) ) <= ( nEndPos - pWMF->Tell() ) )
+ {
+ sal_Unicode* pBuf = new sal_Unicode[ nLen ];
+ pWMF->Read( pBuf, nLen << 1 );
+#ifdef OSL_BIGENDIAN
+ sal_Char nTmp, *pTmp = (sal_Char*)( pBuf + nLen );
+ while ( pTmp-- != (sal_Char*)pBuf )
+ {
+ nTmp = *pTmp--;
+ pTmp[ 1 ] = *pTmp;
+ *pTmp = nTmp;
+ }
+#endif
+ aText = rtl::OUString(pBuf, nLen);
+ delete[] pBuf;
+ }
+ }
+ pOut->DrawText( aPos, aText, pDX, bRecordPath, nGfxMode );
+ }
+ delete[] pDX;
+ }
+ break;
+
+ case EMR_POLYBEZIERTO16 :
+ ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_True);
+ break;
+ case EMR_POLYBEZIER16 :
+ ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYGON16 :
+ ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolygon, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYLINETO16 :
+ ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_True);
+ break;
+ case EMR_POLYLINE16 :
+ ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYPOLYLINE16 :
+ ReadAndDrawPolyLine<sal_Int16>();
+ break;
+
+ case EMR_POLYPOLYGON16 :
+ ReadAndDrawPolyPolygon<sal_Int16>();
+ break;
+
+ case EMR_FILLRGN :
+ {
+ sal_uInt32 nLen;
+ PolyPolygon aPolyPoly;
+ pWMF->SeekRel( 0x10 );
+ *pWMF >> nLen >> nIndex;
+
+ if ( ImplReadRegion( aPolyPoly, *pWMF, nRecSize ) )
+ {
+ pOut->Push();
+ pOut->SelectObject( nIndex );
+ pOut->DrawPolyPolygon( aPolyPoly, sal_False );
+ pOut->Pop();
+ }
+ }
+ break;
+
+ case EMR_CREATEDIBPATTERNBRUSHPT :
+ {
+ sal_uInt32 nStart = pWMF->Tell() - 8;
+ Bitmap aBitmap;
+
+ *pWMF >> nIndex;
+
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ sal_uInt32 usage, offBmi, cbBmi, offBits, cbBits;
+
+ *pWMF >> usage;
+ *pWMF >> offBmi;
+ *pWMF >> cbBmi;
+ *pWMF >> offBits;
+ *pWMF >> cbBits;
+
+ if ( (cbBits > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBits < cbBmi) )
+ bStatus = sal_False;
+ else if ( offBmi )
+ {
+ sal_uInt32 nSize = cbBmi + cbBits + 14;
+ if ( nSize <= ( nEndPos - nStartPos ) )
+ {
+ char* pBuf = new char[ nSize ];
+
+ SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
+ aTmp.ObjectOwnsMemory( sal_True );
+ aTmp << (sal_uInt8)'B'
+ << (sal_uInt8)'M'
+ << (sal_uInt32)cbBits
+ << (sal_uInt16)0
+ << (sal_uInt16)0
+ << (sal_uInt32)cbBmi + 14;
+ pWMF->Seek( nStart + offBmi );
+ pWMF->Read( pBuf + 14, cbBmi );
+ pWMF->Seek( nStart + offBits );
+ pWMF->Read( pBuf + 14 + cbBmi, cbBits );
+ aTmp.Seek( 0 );
+ aBitmap.Read( aTmp, sal_True );
+ }
+ }
+ }
+
+ pOut->CreateObject( nIndex, GDI_BRUSH, new WinMtfFillStyle( aBitmap ) );
+ }
+ break;
+
+#ifdef WIN_MTF_ASSERT
+ default : WinMtfAssertHandler( "Unknown Meta Action" ); break;
+ case EMR_MASKBLT : WinMtfAssertHandler( "MaskBlt" ); break;
+ case EMR_PLGBLT : WinMtfAssertHandler( "PlgBlt" ); break;
+ case EMR_SETDIBITSTODEVICE : WinMtfAssertHandler( "SetDIBitsToDevice" ); break;
+ case EMR_FRAMERGN : WinMtfAssertHandler( "FrameRgn" ); break;
+ case EMR_INVERTRGN : WinMtfAssertHandler( "InvertRgn" ); break;
+ case EMR_PAINTRGN : WinMtfAssertHandler( "PaintRgn" ); break;
+ case EMR_FLATTENPATH : WinMtfAssertHandler( "FlattenPath" ); break;
+ case EMR_WIDENPATH : WinMtfAssertHandler( "WidenPath" ); break;
+ case EMR_POLYDRAW : WinMtfAssertHandler( "Polydraw" ); break;
+ case EMR_SETARCDIRECTION : WinMtfAssertHandler( "SetArcDirection" ); break;
+ case EMR_SETPALETTEENTRIES : WinMtfAssertHandler( "SetPaletteEntries" ); break;
+ case EMR_RESIZEPALETTE : WinMtfAssertHandler( "ResizePalette" ); break;
+ case EMR_EXTFLOODFILL : WinMtfAssertHandler( "ExtFloodFill" ); break;
+ case EMR_ANGLEARC : WinMtfAssertHandler( "AngleArc" ); break;
+ case EMR_SETCOLORADJUSTMENT : WinMtfAssertHandler( "SetColorAdjustment" ); break;
+ case EMR_POLYDRAW16 : WinMtfAssertHandler( "PolyDraw16" ); break;
+ case EMR_POLYTEXTOUTA : WinMtfAssertHandler( "PolyTextOutA" ); break;
+ case EMR_POLYTEXTOUTW : WinMtfAssertHandler( "PolyTextOutW" ); break;
+ case EMR_CREATECOLORSPACE : WinMtfAssertHandler( "CreateColorSpace" ); break;
+ case EMR_SETCOLORSPACE : WinMtfAssertHandler( "SetColorSpace" ); break;
+ case EMR_DELETECOLORSPACE : WinMtfAssertHandler( "DeleteColorSpace" ); break;
+ case EMR_GLSRECORD : WinMtfAssertHandler( "GlsRecord" ); break;
+ case EMR_GLSBOUNDEDRECORD : WinMtfAssertHandler( "GlsBoundRecord" ); break;
+ case EMR_PIXELFORMAT : WinMtfAssertHandler( "PixelFormat" ); break;
+ case EMR_DRAWESCAPE : WinMtfAssertHandler( "DrawEscape" ); break;
+ case EMR_EXTESCAPE : WinMtfAssertHandler( "ExtEscape" ); break;
+ case EMR_STARTDOC : WinMtfAssertHandler( "StartDoc" ); break;
+ case EMR_SMALLTEXTOUT : WinMtfAssertHandler( "SmallTextOut" ); break;
+ case EMR_FORCEUFIMAPPING : WinMtfAssertHandler( "ForceUFIMapping" ); break;
+ case EMR_NAMEDESCAPE : WinMtfAssertHandler( "NamedEscape" ); break;
+ case EMR_COLORCORRECTPALETTE : WinMtfAssertHandler( "ColorCorrectPalette" ); break;
+ case EMR_SETICMPROFILEA : WinMtfAssertHandler( "SetICMProfileA" ); break;
+ case EMR_SETICMPROFILEW : WinMtfAssertHandler( "SetICMProfileW" ); break;
+ case EMR_ALPHABLEND : WinMtfAssertHandler( "Alphablend" ); break;
+ case EMR_TRANSPARENTBLT : WinMtfAssertHandler( "TransparenBlt" ); break;
+ case EMR_TRANSPARENTDIB : WinMtfAssertHandler( "TransparenDib" ); break;
+ case EMR_GRADIENTFILL : WinMtfAssertHandler( "GradientFill" ); break;
+ case EMR_SETLINKEDUFIS : WinMtfAssertHandler( "SetLinkedUFIS" ); break;
+
+ case EMR_SETMAPPERFLAGS : WinMtfAssertHandler( "SetMapperFlags", 0 ); break;
+ case EMR_SETICMMODE : WinMtfAssertHandler( "SetICMMode", 0 ); break;
+ case EMR_CREATEMONOBRUSH : WinMtfAssertHandler( "CreateMonoBrush", 0 ); break;
+ case EMR_SETBRUSHORGEX : WinMtfAssertHandler( "SetBrushOrgEx", 0 ); break;
+ case EMR_SETMETARGN : WinMtfAssertHandler( "SetMetArgn", 0 ); break;
+ case EMR_SETMITERLIMIT : WinMtfAssertHandler( "SetMiterLimit", 0 ); break;
+ case EMR_EXCLUDECLIPRECT : WinMtfAssertHandler( "ExcludeClipRect", 0 ); break;
+ case EMR_REALIZEPALETTE : WinMtfAssertHandler( "RealizePalette", 0 ); break;
+ case EMR_SELECTPALETTE : WinMtfAssertHandler( "SelectPalette", 0 ); break;
+ case EMR_CREATEPALETTE : WinMtfAssertHandler( "CreatePalette", 0 ); break;
+ case EMR_ALPHADIBBLEND : WinMtfAssertHandler( "AlphaDibBlend", 0 ); break;
+ case EMR_SETTEXTJUSTIFICATION : WinMtfAssertHandler( "SetTextJustification", 0 ); break;
+
+ case EMR_GDICOMMENT :
+ case EMR_HEADER : // has already been read at ReadHeader()
+ break;
+#endif
+ }
+ pWMF->Seek( nNextPos );
+ }
+ if( !aBmpSaveList.empty() )
+ pOut->ResolveBitmapActions( aBmpSaveList );
+
+ if ( bStatus )
+ pWMF->Seek(nEndPos);
+
+ return bStatus;
+};
+
+//-----------------------------------------------------------------------------------
+
+sal_Bool EnhWMFReader::ReadHeader()
+{
+ sal_uInt32 nsal_uInt32, nHeaderSize, nPalEntries;
+ sal_Int32 nLeft, nTop, nRight, nBottom;
+
+ // Spare me the METAFILEHEADER here
+ // Reading the METAHEADER
+ *pWMF >> nsal_uInt32 >> nHeaderSize;
+ if ( nsal_uInt32 != 1 ) // Type
+ return sal_False;
+
+ // bound size
+ Rectangle rclBounds; // rectangle in logical units 1/100th mm
+ *pWMF >> nLeft >> nTop >> nRight >> nBottom;
+ rclBounds.Left() = nLeft;
+ rclBounds.Top() = nTop;
+ rclBounds.Right() = nRight;
+ rclBounds.Bottom() = nBottom;
+
+ // picture frame size
+ Rectangle rclFrame; // rectangle in device units
+ *pWMF >> nLeft >> nTop >> nRight >> nBottom;
+ rclFrame.Left() = nLeft;
+ rclFrame.Top() = nTop;
+ rclFrame.Right() = nRight;
+ rclFrame.Bottom() = nBottom;
+
+ *pWMF >> nsal_uInt32; // signature
+
+ if ( nsal_uInt32 != 0x464d4520 )
+ return sal_False;
+
+ *pWMF >> nsal_uInt32; // nVersion
+ *pWMF >> nEndPos; // size of metafile
+ nEndPos += nStartPos;
+
+ sal_uInt32 nStrmPos = pWMF->Tell(); // checking if nEndPos is valid
+ pWMF->Seek( STREAM_SEEK_TO_END );
+ if ( pWMF->Tell() < nEndPos )
+ nEndPos = pWMF->Tell();
+ pWMF->Seek( nStrmPos );
+
+ *pWMF >> nRecordCount;
+
+ if ( !nRecordCount )
+ return sal_False;
+
+ pWMF->SeekRel( 0xc );
+
+ sal_Int32 nPixX, nPixY, nMillX, nMillY;
+ *pWMF >> nPalEntries >> nPixX >> nPixY >> nMillX >> nMillY;
+
+ pOut->SetrclFrame( rclFrame );
+ pOut->SetrclBounds( rclBounds );
+ pOut->SetRefPix( Size( nPixX, nPixY ) );
+ pOut->SetRefMill( Size( nMillX, nMillY ) );
+
+ pWMF->Seek( nStartPos + nHeaderSize );
+ return sal_True;
+}
+
+//-----------------------------------------------------------------------------------
+
+Rectangle EnhWMFReader::ReadRectangle( sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
+{
+ Point aTL ( Point( x1, y1 ) );
+ Point aBR( Point( --x2, --y2 ) );
+ return Rectangle( aTL, aBR );
+}
+
+EnhWMFReader::~EnhWMFReader()
+{
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/winmtf.cxx b/vcl/source/filter/wmf/winmtf.cxx
new file mode 100644
index 000000000000..63b0996b24a3
--- /dev/null
+++ b/vcl/source/filter/wmf/winmtf.cxx
@@ -0,0 +1,2239 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include "winmtf.hxx"
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/graphictools.hxx>
+#include <vcl/canvastools.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/svapp.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/tencinfo.h>
+
+// ------------------------------------------------------------------------
+
+#if OSL_DEBUG_LEVEL > 1
+#define EMFP_DEBUG(x) x
+#else
+#define EMFP_DEBUG(x)
+#endif
+
+void WinMtfClipPath::intersectClipRect( const Rectangle& rRect )
+{
+ maClip.intersectRange(
+ vcl::unotools::b2DRectangleFromRectangle(rRect));
+}
+
+void WinMtfClipPath::excludeClipRect( const Rectangle& rRect )
+{
+ maClip.subtractRange(
+ vcl::unotools::b2DRectangleFromRectangle(rRect));
+}
+
+void WinMtfClipPath::setClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode )
+{
+ const basegfx::B2DPolyPolygon& rB2DPoly=rPolyPolygon.getB2DPolyPolygon();
+ switch ( nClippingMode )
+ {
+ case RGN_OR :
+ maClip.unionPolyPolygon(rB2DPoly);
+ break;
+ case RGN_XOR :
+ maClip.xorPolyPolygon(rB2DPoly);
+ break;
+ case RGN_DIFF :
+ maClip.subtractPolyPolygon(rB2DPoly);
+ break;
+ case RGN_AND :
+ maClip.intersectPolyPolygon(rB2DPoly);
+ break;
+ case RGN_COPY :
+ maClip = basegfx::tools::B2DClipState(rB2DPoly);
+ break;
+ }
+}
+
+void WinMtfClipPath::moveClipRegion( const Size& rSize )
+{
+ // what a weird concept. emulate, don't want this in B2DClipState
+ // API
+ basegfx::B2DPolyPolygon aCurrClip=maClip.getClipPoly();
+ basegfx::B2DHomMatrix aTranslate;
+ aTranslate.translate(rSize.Width(), rSize.Height());
+
+ aCurrClip.transform(aTranslate);
+ maClip = basegfx::tools::B2DClipState( aCurrClip );
+}
+
+basegfx::B2DPolyPolygon WinMtfClipPath::getClipPath() const
+{
+ return maClip.getClipPoly();
+}
+
+// ------------------------------------------------------------------------
+
+void WinMtfPathObj::AddPoint( const Point& rPoint )
+{
+ if ( bClosed )
+ Insert( Polygon(), POLYPOLY_APPEND );
+ Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
+ rPoly.Insert( rPoly.GetSize(), rPoint, POLY_NORMAL );
+ bClosed = sal_False;
+}
+
+void WinMtfPathObj::AddPolyLine( const Polygon& rPolyLine )
+{
+ if ( bClosed )
+ Insert( Polygon(), POLYPOLY_APPEND );
+ Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
+ rPoly.Insert( rPoly.GetSize(), rPolyLine );
+ bClosed = sal_False;
+}
+
+void WinMtfPathObj::AddPolygon( const Polygon& rPoly )
+{
+ Insert( rPoly, POLYPOLY_APPEND );
+ bClosed = sal_True;
+}
+
+void WinMtfPathObj::AddPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ sal_uInt16 i, nCount = rPolyPoly.Count();
+ for ( i = 0; i < nCount; i++ )
+ Insert( rPolyPoly[ i ], POLYPOLY_APPEND );
+ bClosed = sal_True;
+}
+
+void WinMtfPathObj::ClosePath()
+{
+ if ( Count() )
+ {
+ Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
+ if ( rPoly.GetSize() > 2 )
+ {
+ Point aFirst( rPoly[ 0 ] );
+ if ( aFirst != rPoly[ rPoly.GetSize() - 1 ] )
+ rPoly.Insert( rPoly.GetSize(), aFirst, POLY_NORMAL );
+ }
+ }
+ bClosed = sal_True;
+}
+
+// ------------------------------------------------------------------------
+
+WinMtfFontStyle::WinMtfFontStyle( LOGFONTW& rFont )
+{
+ CharSet eCharSet;
+ if ( ( rFont.lfCharSet == OEM_CHARSET ) || ( rFont.lfCharSet == DEFAULT_CHARSET ) )
+ eCharSet = RTL_TEXTENCODING_MS_1252;
+ else
+ eCharSet = rtl_getTextEncodingFromWindowsCharset( rFont.lfCharSet );
+ if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
+ eCharSet = RTL_TEXTENCODING_MS_1252;
+ aFont.SetCharSet( eCharSet );
+ aFont.SetName( rFont.alfFaceName );
+ FontFamily eFamily;
+ switch ( rFont.lfPitchAndFamily & 0xf0 )
+ {
+ case FF_ROMAN:
+ eFamily = FAMILY_ROMAN;
+ break;
+
+ case FF_SWISS:
+ eFamily = FAMILY_SWISS;
+ break;
+
+ case FF_MODERN:
+ eFamily = FAMILY_MODERN;
+ break;
+
+ case FF_SCRIPT:
+ eFamily = FAMILY_SCRIPT;
+ break;
+
+ case FF_DECORATIVE:
+ eFamily = FAMILY_DECORATIVE;
+ break;
+
+ default:
+ eFamily = FAMILY_DONTKNOW;
+ break;
+ }
+ aFont.SetFamily( eFamily );
+
+ FontPitch ePitch;
+ switch ( rFont.lfPitchAndFamily & 0x0f )
+ {
+ case FIXED_PITCH:
+ ePitch = PITCH_FIXED;
+ break;
+
+ case DEFAULT_PITCH:
+ case VARIABLE_PITCH:
+ default:
+ ePitch = PITCH_VARIABLE;
+ break;
+ }
+ aFont.SetPitch( ePitch );
+
+ FontWeight eWeight;
+ if( rFont.lfWeight <= FW_THIN )
+ eWeight = WEIGHT_THIN;
+ else if( rFont.lfWeight <= FW_ULTRALIGHT )
+ eWeight = WEIGHT_ULTRALIGHT;
+ else if( rFont.lfWeight <= FW_LIGHT )
+ eWeight = WEIGHT_LIGHT;
+ else if( rFont.lfWeight < FW_MEDIUM )
+ eWeight = WEIGHT_NORMAL;
+ else if( rFont.lfWeight == FW_MEDIUM )
+ eWeight = WEIGHT_MEDIUM;
+ else if( rFont.lfWeight <= FW_SEMIBOLD )
+ eWeight = WEIGHT_SEMIBOLD;
+ else if( rFont.lfWeight <= FW_BOLD )
+ eWeight = WEIGHT_BOLD;
+ else if( rFont.lfWeight <= FW_ULTRABOLD )
+ eWeight = WEIGHT_ULTRABOLD;
+ else
+ eWeight = WEIGHT_BLACK;
+ aFont.SetWeight( eWeight );
+
+ if( rFont.lfItalic )
+ aFont.SetItalic( ITALIC_NORMAL );
+
+ if( rFont.lfUnderline )
+ aFont.SetUnderline( UNDERLINE_SINGLE );
+
+ if( rFont.lfStrikeOut )
+ aFont.SetStrikeout( STRIKEOUT_SINGLE );
+
+ if ( rFont.lfOrientation )
+ aFont.SetOrientation( (short)rFont.lfOrientation );
+ else
+ aFont.SetOrientation( (short)rFont.lfEscapement );
+
+ Size aFontSize( Size( rFont.lfWidth, rFont.lfHeight ) );
+ if ( rFont.lfHeight > 0 )
+ {
+ // converting the cell height into a font height
+ VirtualDevice aVDev;
+ aFont.SetSize( aFontSize );
+ aVDev.SetFont( aFont );
+ FontMetric aMetric( aVDev.GetFontMetric() );
+ long nHeight = aMetric.GetAscent() + aMetric.GetDescent();
+ if ( nHeight )
+ {
+ double fHeight = ((double)aFontSize.Height() * rFont.lfHeight ) / nHeight;
+ aFontSize.Height() = (sal_Int32)( fHeight + 0.5 );
+ }
+ }
+ else if ( aFontSize.Height() < 0 )
+ aFontSize.Height() *= -1;
+
+ if ( !rFont.lfWidth )
+ {
+ VirtualDevice aVDev;
+ aFont.SetSize( aFontSize );
+ aVDev.SetFont( aFont );
+ FontMetric aMetric( aVDev.GetFontMetric() );
+ aFontSize.Width() = aMetric.GetWidth();
+ }
+
+ aFont.SetSize( aFontSize );
+};
+
+// ------------------------------------------------------------------------
+
+#ifdef WIN_MTF_ASSERT
+void WinMtfAssertHandler( const sal_Char* pAction, sal_uInt32 nFlags )
+{
+ static sal_Bool bOnlyOnce;
+ static sal_Int32 nAssertCount;
+
+ if ( nFlags & WIN_MTF_ASSERT_INIT )
+ nAssertCount = 0;
+ if ( nFlags & WIN_MTF_ASSERT_ONCE )
+ bOnlyOnce = sal_True;
+ if ( nFlags & WIN_MTF_ASSERT_MIFE )
+ {
+ if ( ( nAssertCount == 0 ) || ( bOnlyOnce == sal_False ) )
+ {
+ rtl::OStringBuffer aText(RTL_CONSTASCII_STRINGPARAM(
+ "WMF/EMF Import: "));
+ if (pAction)
+ aText.append(pAction);
+ aText.append(RTL_CONSTASCII_STRINGPARAM(
+ " needs to be implemented"));
+ DBG_ASSERT( 0, aText.getStr() );
+ }
+ nAssertCount++;
+ }
+}
+#endif
+
+// ------------------------------------------------------------------------
+
+WinMtf::WinMtf( WinMtfOutput* pWinMtfOutput, SvStream& rStreamWMF, FilterConfigItem* pConfigItem ) :
+ pOut ( pWinMtfOutput ),
+ pWMF ( &rStreamWMF ),
+ pFilterConfigItem ( pConfigItem )
+{
+#ifdef WIN_MTF_ASSERT
+ // we want to assert not implemented features, but we do this
+ // only once, so that nobody is handicaped by getting too much assertions
+ // I hope this will bring more testdocuments, without support of these
+ // testdocuments the implementation of missing features won't be possible. (SJ)
+ WinMtfAssertHandler( NULL, WIN_MTF_ASSERT_INIT | WIN_MTF_ASSERT_ONCE );
+#endif
+
+ SvLockBytes *pLB = pWMF->GetLockBytes();
+ if ( pLB )
+ pLB->SetSynchronMode( sal_True );
+
+ nStartPos = pWMF->Tell();
+
+ pOut->SetDevOrg( Point() );
+ if ( pFilterConfigItem )
+ {
+ xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
+ if ( xStatusIndicator.is() )
+ {
+ rtl::OUString aMsg;
+ xStatusIndicator->start( aMsg, 100 );
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+WinMtf::~WinMtf()
+{
+ delete pOut;
+
+ if ( xStatusIndicator.is() )
+ xStatusIndicator->end();
+}
+
+// ------------------------------------------------------------------------
+
+void WinMtf::Callback( sal_uInt16 nPercent )
+{
+ if ( xStatusIndicator.is() )
+ xStatusIndicator->setValue( nPercent );
+}
+
+// ------------------------------------------------------------------------
+
+Color WinMtf::ReadColor()
+{
+ sal_uInt32 nColor;
+ *pWMF >> nColor;
+ return Color( (sal_uInt8)nColor, (sal_uInt8)( nColor >> 8 ), (sal_uInt8)( nColor >> 16 ) );
+};
+
+//-----------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------
+
+Point WinMtfOutput::ImplMap( const Point& rPt )
+{
+ if ( mnWinExtX && mnWinExtY )
+ {
+ double fX = rPt.X();
+ double fY = rPt.Y();
+
+ double fX2 = fX * maXForm.eM11 + fY * maXForm.eM21 + maXForm.eDx;
+ double fY2 = fX * maXForm.eM12 + fY * maXForm.eM22 + maXForm.eDy;
+
+ if ( mnGfxMode == GM_COMPATIBLE )
+ {
+ switch( mnMapMode )
+ {
+ case MM_TEXT:
+ fX2 -= mnWinOrgX;
+ fY2 -= mnWinOrgY;
+ if( mnDevWidth != 1 || mnDevHeight != 1 ) {
+ fX2 *= 2540.0/mnUnitsPerInch;
+ fY2 *= 2540.0/mnUnitsPerInch;
+ }
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY;
+ fX2 *= (double)mnMillX * 100.0 / (double)mnPixX;
+ fY2 *= (double)mnMillY * 100.0 / (double)mnPixY;
+
+ break;
+ case MM_LOENGLISH :
+ {
+ fX2 -= mnWinOrgX;
+ fY2 = mnWinOrgY-fY2;
+ fX2 *= 25.40;
+ fY2 *= 25.40;
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY;
+ }
+ break;
+ case MM_HIENGLISH :
+ {
+ fX2 -= mnWinOrgX;
+ fY2 = mnWinOrgY-fY2;
+ fX2 *= 2.540;
+ fY2 *= 2.540;
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY;
+ }
+ break;
+ case MM_LOMETRIC :
+ {
+ fX2 -= mnWinOrgX;
+ fY2 = mnWinOrgY-fY2;
+ fX2 *= 10;
+ fY2 *= 10;
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY;
+ }
+ break;
+ case MM_HIMETRIC :
+ {
+ fX2 -= mnWinOrgX;
+ fY2 = mnWinOrgY-fY2;
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY;
+ }
+ break;
+ default :
+ {
+ fX2 -= mnWinOrgX;
+ fY2 -= mnWinOrgY;
+ fX2 /= mnWinExtX;
+ fY2 /= mnWinExtY;
+ fX2 *= mnDevWidth;
+ fY2 *= mnDevHeight;
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY; // fX2, fY2 now in device units
+ fX2 *= (double)mnMillX * 100.0 / (double)mnPixX;
+ fY2 *= (double)mnMillY * 100.0 / (double)mnPixY;
+ }
+ break;
+ }
+ fX2 -= mrclFrame.Left();
+ fY2 -= mrclFrame.Top();
+ }
+ return Point( FRound( fX2 ), FRound( fY2 ) );
+ }
+ else
+ return Point();
+};
+
+// ------------------------------------------------------------------------
+
+Size WinMtfOutput::ImplMap( const Size& rSz )
+{
+ if ( mnWinExtX && mnWinExtY )
+ {
+ double fWidth = rSz.Width() * maXForm.eM11;
+ double fHeight = rSz.Height() * maXForm.eM22;
+
+ if ( mnGfxMode == GM_COMPATIBLE )
+ {
+ switch( mnMapMode )
+ {
+ case MM_TEXT:
+ if( mnDevWidth != 1 && mnDevHeight != 1 ) {
+ fWidth *= 2540.0/mnUnitsPerInch;
+ fHeight*= 2540.0/mnUnitsPerInch;
+ } else {
+ fWidth *= (double)mnMillX * 100 / (double)mnPixX;
+ fHeight *= (double)mnMillY * 100 / (double)mnPixY;
+ }
+ break;
+ case MM_LOENGLISH :
+ {
+ fWidth *= 25.40;
+ fHeight*=-25.40;
+ }
+ break;
+ case MM_HIENGLISH :
+ {
+ fWidth *= 2.540;
+ fHeight*=-2.540;
+ }
+ break;
+ case MM_LOMETRIC :
+ {
+ fWidth *= 10;
+ fHeight*=-10;
+ }
+ break;
+ case MM_HIMETRIC :
+ {
+ fHeight *= -1;
+ }
+ break;
+ default :
+ {
+ fWidth /= mnWinExtX;
+ fHeight /= mnWinExtY;
+ fWidth *= mnDevWidth;
+ fHeight *= mnDevHeight;
+ fWidth *= (double)mnMillX * 100 / (double)mnPixX;
+ fHeight *= (double)mnMillY * 100 / (double)mnPixY;
+ }
+ break;
+ }
+ }
+ return Size( FRound( fWidth ), FRound( fHeight ) );
+ }
+ else
+ return Size();
+}
+
+//-----------------------------------------------------------------------------------
+
+Rectangle WinMtfOutput::ImplMap( const Rectangle& rRect )
+{
+ return Rectangle( ImplMap( rRect.TopLeft() ), ImplMap( rRect.GetSize() ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ImplMap( Font& rFont )
+{
+ // !!! HACK: Wir setzen die Breite jetzt immer auf Null,
+ // da OS die Breite unterschiedlich interpretieren;
+ // muss spaeter in SV portabel gemacht werden ( KA 08.02.96 )
+ Size aFontSize = ImplMap ( rFont.GetSize() );
+
+ if( aFontSize.Height() < 0 )
+ aFontSize.Height() *= -1;
+
+ rFont.SetSize( aFontSize );
+
+ if( ( mnWinExtX * mnWinExtY ) < 0 )
+ rFont.SetOrientation( 3600 - rFont.GetOrientation() );
+}
+
+//-----------------------------------------------------------------------------------
+
+Polygon& WinMtfOutput::ImplMap( Polygon& rPolygon )
+{
+ sal_uInt16 nPoints = rPolygon.GetSize();
+ for ( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ rPolygon[ i ] = ImplMap( rPolygon[ i ] );
+ }
+ return rPolygon;
+}
+
+//-----------------------------------------------------------------------------------
+
+PolyPolygon& WinMtfOutput::ImplMap( PolyPolygon& rPolyPolygon )
+{
+ sal_uInt16 nPolys = rPolyPolygon.Count();
+ for ( sal_uInt16 i = 0; i < nPolys; ImplMap( rPolyPolygon[ i++ ] ) ) ;
+ return rPolyPolygon;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SelectObject( sal_Int32 nIndex )
+{
+ GDIObj* pGDIObj = NULL;
+
+ if ( nIndex & ENHMETA_STOCK_OBJECT )
+ pGDIObj = new GDIObj();
+ else
+ {
+ nIndex &= 0xffff; // zur Sicherheit: mehr als 65535 nicht zulassen
+
+ if ( (sal_uInt32)nIndex < vGDIObj.size() )
+ pGDIObj = vGDIObj[ nIndex ];
+ }
+
+ if( pGDIObj == NULL )
+ return;
+
+ if ( nIndex & ENHMETA_STOCK_OBJECT )
+ {
+ sal_uInt16 nStockId = (sal_uInt8)nIndex;
+ switch( nStockId )
+ {
+ case WHITE_BRUSH :
+ {
+ pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ) ) );
+ }
+ break;
+ case LTGRAY_BRUSH :
+ {
+ pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_LIGHTGRAY ) ) );
+ }
+ break;
+ case GRAY_BRUSH :
+ case DKGRAY_BRUSH :
+ {
+ pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_GRAY ) ) );
+ }
+ break;
+ case BLACK_BRUSH :
+ {
+ pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_BLACK ) ) );
+ }
+ break;
+ case NULL_BRUSH :
+ {
+ pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_TRANSPARENT ), sal_True ) );
+ }
+ break;
+ case WHITE_PEN :
+ {
+ pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_WHITE ) ) );
+ }
+ break;
+ case BLACK_PEN :
+ {
+ pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_BLACK ) ) );
+ }
+ break;
+ case NULL_PEN :
+ {
+ pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_TRANSPARENT ), sal_True ) );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if ( pGDIObj->pStyle )
+ {
+ switch( pGDIObj->eType )
+ {
+ case GDI_PEN :
+ maLineStyle = (WinMtfLineStyle*)pGDIObj->pStyle;
+ break;
+ case GDI_BRUSH :
+ {
+ maFillStyle = (WinMtfFillStyle*)pGDIObj->pStyle;
+ mbFillStyleSelected = sal_True;
+ }
+ break;
+ case GDI_FONT :
+ maFont = ((WinMtfFontStyle*)pGDIObj->pStyle)->aFont;
+ break;
+ default:
+ break; // -Wall many options not handled.
+ }
+ }
+ if ( nIndex & ENHMETA_STOCK_OBJECT )
+ delete pGDIObj;
+}
+
+//-----------------------------------------------------------------------------------
+
+const Font& WinMtfOutput::GetFont() const
+{
+ return maFont;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetTextLayoutMode( const sal_uInt32 nTextLayoutMode )
+{
+ mnTextLayoutMode = nTextLayoutMode;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetBkMode( sal_uInt32 nMode )
+{
+ mnBkMode = nMode;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetBkColor( const Color& rColor )
+{
+ maBkColor = rColor;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetTextColor( const Color& rColor )
+{
+ maTextColor = rColor;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetTextAlign( sal_uInt32 nAlign )
+{
+ mnTextAlign = nAlign;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ImplResizeObjectArry( sal_uInt32 nNewEntrys )
+{
+ sal_uInt32 i = vGDIObj.size();
+ vGDIObj.resize( nNewEntrys );
+ for ( ; i < nNewEntrys ; i++ )
+ vGDIObj[ i ] = NULL;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ImplDrawClippedPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ if ( rPolyPoly.Count() )
+ {
+ ImplSetNonPersistentLineColorTransparenz();
+ if ( rPolyPoly.Count() == 1 )
+ {
+ if ( rPolyPoly.IsRect() )
+ mpGDIMetaFile->AddAction( new MetaRectAction( rPolyPoly.GetBoundRect() ) );
+ else
+ {
+ Polygon aPoly( rPolyPoly[ 0 ] );
+ sal_uInt16 nCount = aPoly.GetSize();
+ if ( nCount )
+ {
+ if ( aPoly[ nCount - 1 ] != aPoly[ 0 ] )
+ {
+ Point aPoint( aPoly[ 0 ] );
+ aPoly.Insert( nCount, aPoint );
+ }
+ mpGDIMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
+ }
+ }
+ }
+ else
+ mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) );
+ }
+}
+
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::CreateObject( GDIObjectType eType, void* pStyle )
+{
+ if ( pStyle )
+ {
+ if ( eType == GDI_FONT )
+ {
+ ImplMap( ((WinMtfFontStyle*)pStyle)->aFont );
+ if (!((WinMtfFontStyle*)pStyle)->aFont.GetHeight() )
+ ((WinMtfFontStyle*)pStyle)->aFont.SetHeight( 423 ); // defaulting to 12pt
+ }
+ else if ( eType == GDI_PEN )
+ {
+ Size aSize( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetWidth(), 0 );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetWidth( ImplMap( aSize ).Width() );
+ if ( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetStyle() == LINE_DASH )
+ {
+ aSize.Width() += 1;
+ long nDotLen = ImplMap( aSize ).Width();
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDistance( nDotLen );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDotLen( nDotLen );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDashLen( nDotLen * 4 );
+ }
+ }
+ }
+ sal_uInt32 nIndex;
+ for ( nIndex = 0; nIndex < vGDIObj.size(); nIndex++ )
+ {
+ if ( vGDIObj[ nIndex ] == NULL )
+ break;
+ }
+ if ( nIndex == vGDIObj.size() )
+ ImplResizeObjectArry( vGDIObj.size() + 16 );
+
+ vGDIObj[ nIndex ] = new GDIObj( eType, pStyle );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::CreateObject( sal_Int32 nIndex, GDIObjectType eType, void* pStyle )
+{
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ nIndex &= 0xffff; // zur Sicherheit: mehr als 65535 nicht zulassen
+ if ( pStyle )
+ {
+ if ( eType == GDI_FONT )
+ ImplMap( ((WinMtfFontStyle*)pStyle)->aFont );
+ else if ( eType == GDI_PEN )
+ {
+ Size aSize( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetWidth(), 0 );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetWidth( ImplMap( aSize ).Width() );
+ if ( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetStyle() == LINE_DASH )
+ {
+ aSize.Width() += 1;
+ long nDotLen = ImplMap( aSize ).Width();
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDistance( nDotLen );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDotLen( nDotLen );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDashLen( nDotLen * 4 );
+ }
+ }
+ }
+ if ( (sal_uInt32)nIndex >= vGDIObj.size() )
+ ImplResizeObjectArry( nIndex + 16 );
+
+ if ( vGDIObj[ nIndex ] != NULL )
+ delete vGDIObj[ nIndex ];
+
+ vGDIObj[ nIndex ] = new GDIObj( eType, pStyle );
+ }
+ else
+ {
+ switch ( eType )
+ {
+ case GDI_PEN :
+ delete (WinMtfLineStyle*)pStyle;
+ break;
+ case GDI_BRUSH :
+ delete (WinMtfFillStyle*)pStyle;
+ break;
+ case GDI_FONT :
+ delete (WinMtfFontStyle*)pStyle;
+ break;
+
+ default:
+ OSL_FAIL( "unsupported style not deleted" );
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DeleteObject( sal_Int32 nIndex )
+{
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ if ( (sal_uInt32)nIndex < vGDIObj.size() )
+ {
+ delete vGDIObj[ nIndex ];
+ vGDIObj[ nIndex ] = NULL;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::IntersectClipRect( const Rectangle& rRect )
+{
+ mbClipNeedsUpdate=true;
+ aClipPath.intersectClipRect( ImplMap( rRect ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ExcludeClipRect( const Rectangle& rRect )
+{
+ mbClipNeedsUpdate=true;
+ aClipPath.excludeClipRect( ImplMap( rRect ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::MoveClipRegion( const Size& rSize )
+{
+ mbClipNeedsUpdate=true;
+ aClipPath.moveClipRegion( ImplMap( rSize ) );
+}
+
+void WinMtfOutput::SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode, sal_Bool bIsMapped )
+{
+ mbClipNeedsUpdate=true;
+ if ( bIsMapped )
+ aClipPath.setClipPath( rPolyPolygon, nClippingMode );
+ else
+ {
+ PolyPolygon aPP( rPolyPolygon );
+ aClipPath.setClipPath( ImplMap( aPP ), nClippingMode );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------
+
+WinMtfOutput::WinMtfOutput( GDIMetaFile& rGDIMetaFile ) :
+ mnLatestTextAlign ( 0 ),
+ mnTextAlign ( TA_LEFT | TA_TOP | TA_NOUPDATECP ),
+ maLatestBkColor ( 0x12345678 ),
+ maBkColor ( COL_WHITE ),
+ mnLatestTextLayoutMode( TEXT_LAYOUT_DEFAULT ),
+ mnTextLayoutMode ( TEXT_LAYOUT_DEFAULT ),
+ mnLatestBkMode ( 0 ),
+ mnBkMode ( OPAQUE ),
+ meLatestRasterOp ( ROP_INVERT ),
+ meRasterOp ( ROP_OVERPAINT ),
+ maActPos ( Point() ),
+ mbNopMode ( sal_False ),
+ mbFillStyleSelected ( sal_False ),
+ mbClipNeedsUpdate ( true ),
+ mbComplexClip ( false ),
+ mnGfxMode ( GM_COMPATIBLE ),
+ mnMapMode ( MM_TEXT ),
+ mnUnitsPerInch ( 96 ),
+ mnDevOrgX ( 0 ),
+ mnDevOrgY ( 0 ),
+ mnDevWidth ( 1 ),
+ mnDevHeight ( 1 ),
+ mnWinOrgX ( 0 ),
+ mnWinOrgY ( 0 ),
+ mnWinExtX ( 1 ),
+ mnWinExtY ( 1 ),
+ mnPixX ( 100 ),
+ mnPixY ( 100 ),
+ mnMillX ( 1 ),
+ mnMillY ( 1 ),
+ mpGDIMetaFile ( &rGDIMetaFile )
+{
+ mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); // The original clipregion has to be on top
+ // of the stack so it can always be restored
+ // this is necessary to be able to support
+ // SetClipRgn( NULL ) and similar ClipRgn actions (SJ)
+
+ maFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "Arial" )) ); // sj: #i57205#, we do have some scaling problems if using
+ maFont.SetCharSet( RTL_TEXTENCODING_MS_1252 ); // the default font then most times a x11 font is used, we
+ maFont.SetHeight( 423 ); // will prevent this defining a font
+
+ maLatestLineStyle.aLineColor = Color( 0x12, 0x34, 0x56 );
+ maLatestFillStyle.aFillColor = Color( 0x12, 0x34, 0x56 );
+
+ mnRop = R2_BLACK + 1;
+ SetRasterOp( R2_BLACK );
+};
+
+//-----------------------------------------------------------------------------------
+
+WinMtfOutput::~WinMtfOutput()
+{
+ mpGDIMetaFile->AddAction( new MetaPopAction() );
+ mpGDIMetaFile->SetPrefMapMode( MAP_100TH_MM );
+ if ( mrclFrame.IsEmpty() )
+ mpGDIMetaFile->SetPrefSize( Size( mnDevWidth, mnDevHeight ) );
+ else
+ mpGDIMetaFile->SetPrefSize( mrclFrame.GetSize() );
+
+ for ( sal_uInt32 i = 0; i < vGDIObj.size(); i++ )
+ delete vGDIObj[ i ];
+};
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::UpdateClipRegion()
+{
+ if ( mbClipNeedsUpdate )
+ {
+ mbClipNeedsUpdate = false;
+ mbComplexClip = false;
+
+ mpGDIMetaFile->AddAction( new MetaPopAction() ); // taking the orignal clipregion
+ mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); //
+
+ // skip for 'no clipping at all' case
+ if( !aClipPath.isEmpty() )
+ {
+ const basegfx::B2DPolyPolygon& rClipPoly( aClipPath.getClipPath() );
+ mpGDIMetaFile->AddAction(
+ new MetaISectRectClipRegionAction(
+ vcl::unotools::rectangleFromB2DRectangle(
+ rClipPoly.getB2DRange())));
+
+ mbComplexClip = rClipPoly.count() > 1
+ || !basegfx::tools::isRectangle(rClipPoly);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ImplSetNonPersistentLineColorTransparenz()
+{
+ Color aColor( COL_TRANSPARENT);
+ WinMtfLineStyle aTransparentLine( aColor, sal_True );
+ if ( ! ( maLatestLineStyle == aTransparentLine ) )
+ {
+ maLatestLineStyle = aTransparentLine;
+ mpGDIMetaFile->AddAction( new MetaLineColorAction( aTransparentLine.aLineColor, !aTransparentLine.bTransparent ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::UpdateLineStyle()
+{
+ if (!( maLatestLineStyle == maLineStyle ) )
+ {
+ maLatestLineStyle = maLineStyle;
+ mpGDIMetaFile->AddAction( new MetaLineColorAction( maLineStyle.aLineColor, !maLineStyle.bTransparent ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::UpdateFillStyle()
+{
+ if ( !mbFillStyleSelected ) // SJ: #i57205# taking care of bkcolor if no brush is selected
+ maFillStyle = WinMtfFillStyle( maBkColor, mnBkMode == TRANSPARENT );
+ if (!( maLatestFillStyle == maFillStyle ) )
+ {
+ maLatestFillStyle = maFillStyle;
+ if (maFillStyle.aType == FillStyleSolid)
+ mpGDIMetaFile->AddAction( new MetaFillColorAction( maFillStyle.aFillColor, !maFillStyle.bTransparent ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+sal_uInt32 WinMtfOutput::SetRasterOp( sal_uInt32 nRasterOp )
+{
+ sal_uInt32 nRetROP = mnRop;
+ if ( nRasterOp != mnRop )
+ {
+ mnRop = nRasterOp;
+ static WinMtfFillStyle aNopFillStyle;
+ static WinMtfLineStyle aNopLineStyle;
+
+ if ( mbNopMode && ( nRasterOp != R2_NOP ) )
+ { // beim uebergang von R2_NOP auf anderen Modus
+ // gesetzten Pen und Brush aktivieren
+ maFillStyle = aNopFillStyle;
+ maLineStyle = aNopLineStyle;
+ mbNopMode = sal_False;
+ }
+ switch( nRasterOp )
+ {
+ case R2_NOT:
+ meRasterOp = ROP_INVERT;
+ break;
+
+ case R2_XORPEN:
+ meRasterOp = ROP_XOR;
+ break;
+
+ case R2_NOP:
+ {
+ meRasterOp = ROP_OVERPAINT;
+ if( mbNopMode == sal_False )
+ {
+ aNopFillStyle = maFillStyle;
+ aNopLineStyle = maLineStyle;
+ maFillStyle = WinMtfFillStyle( Color( COL_TRANSPARENT ), sal_True );
+ maLineStyle = WinMtfLineStyle( Color( COL_TRANSPARENT ), sal_True );
+ mbNopMode = sal_True;
+ }
+ }
+ break;
+
+ default:
+ meRasterOp = ROP_OVERPAINT;
+ break;
+ }
+ }
+ if ( nRetROP != nRasterOp )
+ mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
+ return nRetROP;
+};
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::StrokeAndFillPath( sal_Bool bStroke, sal_Bool bFill )
+{
+ if ( aPathObj.Count() )
+ {
+ UpdateClipRegion();
+ UpdateLineStyle();
+ UpdateFillStyle();
+ if ( bFill )
+ {
+ if ( !bStroke )
+ {
+ mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ mpGDIMetaFile->AddAction( new MetaLineColorAction( Color(), sal_False ) );
+ }
+ if ( aPathObj.Count() == 1 )
+ mpGDIMetaFile->AddAction( new MetaPolygonAction( aPathObj.GetObject( 0 ) ) );
+ else
+ mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aPathObj ) );
+
+ if ( !bStroke )
+ mpGDIMetaFile->AddAction( new MetaPopAction() );
+ }
+ else
+ {
+ sal_uInt16 i, nCount = aPathObj.Count();
+ for ( i = 0; i < nCount; i++ )
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( aPathObj[ i ], maLineStyle.aLineInfo ) );
+ }
+ ClearPath();
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPixel( const Point& rSource, const Color& rColor )
+{
+ mpGDIMetaFile->AddAction( new MetaPixelAction( ImplMap( rSource), rColor ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::MoveTo( const Point& rPoint, sal_Bool bRecordPath )
+{
+ Point aDest( ImplMap( rPoint ) );
+ if ( bRecordPath )
+ {
+ // fdo#57353 create new subpath for subsequent moves
+ if ( aPathObj.Count() )
+ if ( aPathObj[ aPathObj.Count() - 1 ].GetSize() )
+ aPathObj.Insert( Polygon(), POLYPOLY_APPEND );
+ aPathObj.AddPoint( aDest );
+ }
+ maActPos = aDest;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::LineTo( const Point& rPoint, sal_Bool bRecordPath )
+{
+ UpdateClipRegion();
+
+ Point aDest( ImplMap( rPoint ) );
+ if ( bRecordPath )
+ aPathObj.AddPoint( aDest );
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaLineAction( maActPos, aDest, maLineStyle.aLineInfo ) );
+ }
+ maActPos = aDest;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawRect( const Rectangle& rRect, sal_Bool bEdge )
+{
+ UpdateClipRegion();
+ UpdateFillStyle();
+
+ if ( mbComplexClip )
+ {
+ Polygon aPoly( ImplMap( rRect ) );
+ PolyPolygon aPolyPolyRect( aPoly );
+ PolyPolygon aDest;
+ PolyPolygon(aClipPath.getClipPath()).GetIntersection( aPolyPolyRect, aDest );
+ ImplDrawClippedPolyPolygon( aDest );
+ }
+ else
+ {
+ if ( bEdge )
+ {
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( ImplMap( rRect ) ),maLineStyle.aLineInfo ) );
+ }
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
+ }
+ }
+ else
+ {
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawRoundRect( const Rectangle& rRect, const Size& rSize )
+{
+ UpdateClipRegion();
+ UpdateLineStyle();
+ UpdateFillStyle();
+ mpGDIMetaFile->AddAction( new MetaRoundRectAction( ImplMap( rRect ), labs( ImplMap( rSize ).Width() ), labs( ImplMap( rSize ).Height() ) ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawEllipse( const Rectangle& rRect )
+{
+ UpdateClipRegion();
+ UpdateFillStyle();
+
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ Point aCenter( ImplMap( rRect.Center() ) );
+ Size aRad( ImplMap( Size( rRect.GetWidth() / 2, rRect.GetHeight() / 2 ) ) );
+
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
+ }
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawArc( const Rectangle& rRect, const Point& rStart, const Point& rEnd, sal_Bool bTo )
+{
+ UpdateClipRegion();
+ UpdateLineStyle();
+ UpdateFillStyle();
+
+ Rectangle aRect( ImplMap( rRect ) );
+ Point aStart( ImplMap( rStart ) );
+ Point aEnd( ImplMap( rEnd ) );
+
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ if ( aStart == aEnd )
+ { // SJ: #i53768# if start & end is identical, then we have to draw a full ellipse
+ Point aCenter( aRect.Center() );
+ Size aRad( aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
+
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
+ }
+ else
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_ARC ), maLineStyle.aLineInfo ) );
+ }
+ else
+ mpGDIMetaFile->AddAction( new MetaArcAction( aRect, aStart, aEnd ) );
+
+ if ( bTo )
+ maActPos = aEnd;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPie( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
+{
+ UpdateClipRegion();
+ UpdateFillStyle();
+
+ Rectangle aRect( ImplMap( rRect ) );
+ Point aStart( ImplMap( rStart ) );
+ Point aEnd( ImplMap( rEnd ) );
+
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_PIE ), maLineStyle.aLineInfo ) );
+ }
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawChord( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
+{
+ UpdateClipRegion();
+ UpdateFillStyle();
+
+ Rectangle aRect( ImplMap( rRect ) );
+ Point aStart( ImplMap( rStart ) );
+ Point aEnd( ImplMap( rEnd ) );
+
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_CHORD ), maLineStyle.aLineInfo ) );
+ }
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPolygon( Polygon& rPolygon, sal_Bool bRecordPath )
+{
+ UpdateClipRegion();
+ ImplMap( rPolygon );
+ if ( bRecordPath )
+ aPathObj.AddPolygon( rPolygon );
+ else
+ {
+ UpdateFillStyle();
+
+ if ( mbComplexClip )
+ {
+ PolyPolygon aPolyPoly( rPolygon );
+ PolyPolygon aDest;
+ PolyPolygon(aClipPath.getClipPath()).GetIntersection( aPolyPoly, aDest );
+ ImplDrawClippedPolyPolygon( aDest );
+ }
+ else
+ {
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ sal_uInt16 nCount = rPolygon.GetSize();
+ if ( nCount )
+ {
+ if ( rPolygon[ nCount - 1 ] != rPolygon[ 0 ] )
+ {
+ Point aPoint( rPolygon[ 0 ] );
+ rPolygon.Insert( nCount, aPoint );
+ }
+ }
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
+ }
+ else
+ {
+ UpdateLineStyle();
+
+ if (maLatestFillStyle.aType != FillStylePattern)
+ mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
+ else {
+ SvtGraphicFill aFill = SvtGraphicFill( PolyPolygon( rPolygon ),
+ Color(),
+ 0.0,
+ SvtGraphicFill::fillNonZero,
+ SvtGraphicFill::fillTexture,
+ SvtGraphicFill::Transform(),
+ true,
+ SvtGraphicFill::hatchSingle,
+ Color(),
+ SvtGraphicFill::gradientLinear,
+ Color(),
+ Color(),
+ 0,
+ Graphic (maLatestFillStyle.aBmp) );
+
+ SvMemoryStream aMemStm;
+
+ aMemStm << aFill;
+
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
+ static_cast<const sal_uInt8*>(aMemStm.GetData()),
+ aMemStm.Seek( STREAM_SEEK_TO_END ) ) );
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_END" ) );
+ }
+
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPolyPolygon( PolyPolygon& rPolyPolygon, sal_Bool bRecordPath )
+{
+ UpdateClipRegion();
+
+ ImplMap( rPolyPolygon );
+
+ if ( bRecordPath )
+ aPathObj.AddPolyPolygon( rPolyPolygon );
+ else
+ {
+ UpdateFillStyle();
+
+ if ( mbComplexClip )
+ {
+ PolyPolygon aDest;
+ PolyPolygon(aClipPath.getClipPath()).GetIntersection( rPolyPolygon, aDest );
+ ImplDrawClippedPolyPolygon( aDest );
+ }
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPolygon ) );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPolyLine( Polygon& rPolygon, sal_Bool bTo, sal_Bool bRecordPath )
+{
+ UpdateClipRegion();
+
+ ImplMap( rPolygon );
+ if ( bTo )
+ {
+ rPolygon[ 0 ] = maActPos;
+ maActPos = rPolygon[ rPolygon.GetSize() - 1 ];
+ }
+ if ( bRecordPath )
+ aPathObj.AddPolyLine( rPolygon );
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPolyBezier( Polygon& rPolygon, sal_Bool bTo, sal_Bool bRecordPath )
+{
+ UpdateClipRegion();
+
+ sal_uInt16 nPoints = rPolygon.GetSize();
+ if ( ( nPoints >= 4 ) && ( ( ( nPoints - 4 ) % 3 ) == 0 ) )
+ {
+ ImplMap( rPolygon );
+ if ( bTo )
+ {
+ rPolygon[ 0 ] = maActPos;
+ maActPos = rPolygon[ nPoints - 1 ];
+ }
+ sal_uInt16 i;
+ for ( i = 0; ( i + 2 ) < nPoints; )
+ {
+ rPolygon.SetFlags( i++, POLY_NORMAL );
+ rPolygon.SetFlags( i++, POLY_CONTROL );
+ rPolygon.SetFlags( i++, POLY_CONTROL );
+ }
+ if ( bRecordPath )
+ aPathObj.AddPolyLine( rPolygon );
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawText( Point& rPosition, String& rText, sal_Int32* pDXArry, sal_Bool bRecordPath, sal_Int32 nGfxMode )
+{
+ UpdateClipRegion();
+
+ VirtualDevice* pVDev = NULL;
+
+ rPosition = ImplMap( rPosition );
+
+ sal_Int32 nOldGfxMode = GetGfxMode();
+ SetGfxMode( GM_COMPATIBLE );
+ if ( pDXArry )
+ {
+ sal_Int32 i, nSum, nLen = rText.Len();
+
+ for( i = 0, nSum = 0; i < nLen; i++ )
+ {
+ if ( i ) {
+ pDXArry[ i - 1 ] = ImplMap( Size( nSum, 0 ) ).Width();
+ }
+ nSum += pDXArry[ i ];
+ }
+ }
+ if ( mnLatestTextLayoutMode != mnTextLayoutMode )
+ {
+ mnLatestTextLayoutMode = mnTextLayoutMode;
+ mpGDIMetaFile->AddAction( new MetaLayoutModeAction( mnTextLayoutMode ) );
+ }
+ SetGfxMode( nGfxMode );
+ sal_Bool bChangeFont = sal_False;
+ if ( mnLatestTextAlign != mnTextAlign )
+ {
+ bChangeFont = sal_True;
+ mnLatestTextAlign = mnTextAlign;
+ TextAlign eTextAlign;
+ if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
+ eTextAlign = ALIGN_BASELINE;
+ else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
+ eTextAlign = ALIGN_BOTTOM;
+ else
+ eTextAlign = ALIGN_TOP;
+ mpGDIMetaFile->AddAction( new MetaTextAlignAction( eTextAlign ) );
+ }
+ if ( maLatestTextColor != maTextColor )
+ {
+ bChangeFont = sal_True;
+ maLatestTextColor = maTextColor;
+ mpGDIMetaFile->AddAction( new MetaTextColorAction( maTextColor ) );
+ }
+ sal_Bool bChangeFillColor = sal_False;
+ if ( maLatestBkColor != maBkColor )
+ {
+ bChangeFillColor = sal_True;
+ maLatestBkColor = maBkColor;
+ }
+ if ( mnLatestBkMode != mnBkMode )
+ {
+ bChangeFillColor = sal_True;
+ mnLatestBkMode = mnBkMode;
+ }
+ if ( bChangeFillColor )
+ {
+ bChangeFont = sal_True;
+ mpGDIMetaFile->AddAction( new MetaTextFillColorAction( maFont.GetFillColor(), !maFont.IsTransparent() ) );
+ }
+ Font aTmp( maFont );
+ aTmp.SetColor( maTextColor );
+ aTmp.SetFillColor( maBkColor );
+
+ if( mnBkMode == TRANSPARENT )
+ aTmp.SetTransparent( sal_True );
+ else
+ aTmp.SetTransparent( sal_False );
+
+ if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
+ aTmp.SetAlign( ALIGN_BASELINE );
+ else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
+ aTmp.SetAlign( ALIGN_BOTTOM );
+ else
+ aTmp.SetAlign( ALIGN_TOP );
+
+ if ( nGfxMode == GM_ADVANCED )
+ {
+ // check whether there is a font rotation applied via transformation
+ Point aP1( ImplMap( Point() ) );
+ Point aP2( ImplMap( Point( 0, 100 ) ) );
+ aP2.X() -= aP1.X();
+ aP2.Y() -= aP1.Y();
+ double fX = aP2.X();
+ double fY = aP2.Y();
+ if ( fX )
+ {
+ double fOrientation = acos( fX / sqrt( fX * fX + fY * fY ) ) * 57.29577951308;
+ if ( fY > 0 )
+ fOrientation = 360 - fOrientation;
+ fOrientation += 90;
+ fOrientation *= 10;
+ fOrientation += aTmp.GetOrientation();
+ aTmp.SetOrientation( sal_Int16( fOrientation ) );
+ }
+ }
+
+ if( mnTextAlign & ( TA_UPDATECP | TA_RIGHT_CENTER ) )
+ {
+ if ( !pVDev )
+ pVDev = new VirtualDevice;
+ sal_Int32 nTextWidth;
+ pVDev->SetMapMode( MapMode( MAP_100TH_MM ) );
+ pVDev->SetFont( maFont );
+ if( pDXArry )
+ {
+ sal_uInt32 nLen = rText.Len();
+ nTextWidth = pVDev->GetTextWidth( rtl::OUString(rText.GetChar( (sal_uInt16)( nLen - 1 ) )) );
+ if( nLen > 1 )
+ nTextWidth += pDXArry[ nLen - 2 ];
+ }
+ else
+ nTextWidth = pVDev->GetTextWidth( rText );
+
+ if( mnTextAlign & TA_UPDATECP )
+ rPosition = maActPos;
+
+ if ( mnTextAlign & TA_RIGHT_CENTER )
+ {
+ double fLenght = ( ( mnTextAlign & TA_RIGHT_CENTER ) == TA_RIGHT ) ? nTextWidth : nTextWidth >> 1;
+ rPosition.X() -= (sal_Int32)( fLenght * cos( maFont.GetOrientation() * F_PI1800 ) );
+ rPosition.Y() -= (sal_Int32)(-( fLenght * sin( maFont.GetOrientation() * F_PI1800 ) ) );
+ }
+
+ if( mnTextAlign & TA_UPDATECP )
+ maActPos.X() = rPosition.X() + nTextWidth;
+ }
+ if ( bChangeFont || ( maLatestFont != aTmp ) )
+ {
+ maLatestFont = aTmp;
+ mpGDIMetaFile->AddAction( new MetaFontAction( aTmp ) );
+ mpGDIMetaFile->AddAction( new MetaTextAlignAction( aTmp.GetAlign() ) );
+ mpGDIMetaFile->AddAction( new MetaTextColorAction( aTmp.GetColor() ) );
+ mpGDIMetaFile->AddAction( new MetaTextFillColorAction( aTmp.GetFillColor(), !aTmp.IsTransparent() ) );
+ }
+ if ( bRecordPath )
+ {
+ // ToDo
+ }
+ else
+ {
+ /* because text without dx array is badly scaled, we
+ will create such an array if necessary */
+ sal_Int32* pDX = pDXArry;
+ if ( !pDXArry )
+ {
+ SolarMutexGuard aGuard;
+
+ pDX = new sal_Int32[ rText.Len() ];
+ if ( !pVDev )
+ pVDev = new VirtualDevice;
+ pVDev->SetMapMode( MAP_100TH_MM );
+ pVDev->SetFont( maLatestFont );
+ pVDev->GetTextArray( rText, pDX, 0, STRING_LEN );
+ }
+ mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, 0, STRING_LEN ) );
+ if ( !pDXArry ) // this means we have created our own array
+ delete[] pDX; // which must be deleted
+ }
+ SetGfxMode( nOldGfxMode );
+ delete pVDev;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ImplDrawBitmap( const Point& rPos, const Size& rSize, const BitmapEx rBitmap )
+{
+ BitmapEx aBmpEx( rBitmap );
+ if ( mbComplexClip )
+ {
+ VirtualDevice aVDev;
+ MapMode aMapMode( MAP_100TH_MM );
+ aMapMode.SetOrigin( Point( -rPos.X(), -rPos.Y() ) );
+ const Size aOutputSizePixel( aVDev.LogicToPixel( rSize, aMapMode ) );
+ const Size aSizePixel( rBitmap.GetSizePixel() );
+ if ( aOutputSizePixel.Width() && aOutputSizePixel.Height() )
+ {
+ aMapMode.SetScaleX( Fraction( aSizePixel.Width(), aOutputSizePixel.Width() ) );
+ aMapMode.SetScaleY( Fraction( aSizePixel.Height(), aOutputSizePixel.Height() ) );
+ }
+ aVDev.SetMapMode( aMapMode );
+ aVDev.SetOutputSizePixel( aSizePixel );
+ aVDev.SetFillColor( Color( COL_BLACK ) );
+ const PolyPolygon aClip( aClipPath.getClipPath() );
+ aVDev.DrawPolyPolygon( aClip );
+ const Point aEmptyPoint;
+
+ // #i50672# Extract whole VDev content (to match size of rBitmap)
+ aVDev.EnableMapMode( sal_False );
+ Bitmap aMask( aVDev.GetBitmap( aEmptyPoint, aSizePixel ).CreateMask( Color( COL_WHITE ) ) );
+
+ if ( aBmpEx.IsTransparent() )
+ {
+ if ( rBitmap.GetTransparentColor() == Color( COL_WHITE ) )
+ aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_OR );
+ else
+ aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_AND );
+ aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask );
+ }
+ else
+ aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask );
+ }
+ if ( aBmpEx.IsTransparent() )
+ mpGDIMetaFile->AddAction( new MetaBmpExScaleAction( rPos, rSize, aBmpEx ) );
+ else
+ mpGDIMetaFile->AddAction( new MetaBmpScaleAction( rPos, rSize, aBmpEx.GetBitmap() ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ResolveBitmapActions( BSaveStructList_impl& rSaveList )
+{
+ UpdateClipRegion();
+
+ size_t nObjects = rSaveList.size();
+ size_t nObjectsLeft = nObjects;
+
+ while ( nObjectsLeft )
+ {
+ size_t i;
+ size_t nObjectsOfSameSize = 0;
+ size_t nObjectStartIndex = nObjects - nObjectsLeft;
+
+ BSaveStruct* pSave = rSaveList[ nObjectStartIndex ];
+ Rectangle aRect( pSave->aOutRect );
+
+ for ( i = nObjectStartIndex; i < nObjects; )
+ {
+ nObjectsOfSameSize++;
+ if ( ++i < nObjects )
+ {
+ pSave = rSaveList[ i ];
+ if ( pSave->aOutRect != aRect )
+ break;
+ }
+ }
+ Point aPos( ImplMap( aRect.TopLeft() ) );
+ Size aSize( ImplMap( aRect.GetSize() ) );
+
+ for ( i = nObjectStartIndex; i < ( nObjectStartIndex + nObjectsOfSameSize ); i++ )
+ {
+ pSave = rSaveList[ i ];
+
+ sal_uInt32 nWinRop = pSave->nWinRop;
+ sal_uInt8 nRasterOperation = (sal_uInt8)( nWinRop >> 16 );
+
+ sal_uInt32 nUsed = 0;
+ if ( ( nRasterOperation & 0xf ) != ( nRasterOperation >> 4 ) )
+ nUsed |= 1; // pattern is used
+ if ( ( nRasterOperation & 0x33 ) != ( ( nRasterOperation & 0xcc ) >> 2 ) )
+ nUsed |= 2; // source is used
+ if ( ( nRasterOperation & 0xaa ) != ( ( nRasterOperation & 0x55 ) << 1 ) )
+ nUsed |= 4; // destination is used
+
+ if ( (nUsed & 1) && (( nUsed & 2 ) == 0) && nWinRop != PATINVERT )
+ { // patterns aren't well supported yet
+ sal_uInt32 nOldRop = SetRasterOp( ROP_OVERPAINT ); // in this case nRasterOperation is either 0 or 0xff
+ UpdateFillStyle();
+ DrawRect( aRect, sal_False );
+ SetRasterOp( nOldRop );
+ }
+ else
+ {
+ sal_Bool bDrawn = sal_False;
+
+ if ( i == nObjectStartIndex ) // optimizing, sometimes it is possible to create just one transparent bitmap
+ {
+ if ( nObjectsOfSameSize == 2 )
+ {
+ BSaveStruct* pSave2 = rSaveList[ i + 1 ];
+ if ( ( pSave->aBmp.GetPrefSize() == pSave2->aBmp.GetPrefSize() ) &&
+ ( pSave->aBmp.GetPrefMapMode() == pSave2->aBmp.GetPrefMapMode() ) )
+ {
+ // TODO: Strictly speaking, we should
+ // check whether mask is monochrome, and
+ // whether image is black (upper branch)
+ // or white (lower branch). Otherwise, the
+ // effect is not the same as a masked
+ // bitmap.
+ if ( ( nWinRop == SRCPAINT ) && ( pSave2->nWinRop == SRCAND ) )
+ {
+ Bitmap aMask( pSave->aBmp ); aMask.Invert();
+ BitmapEx aBmpEx( pSave2->aBmp, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ bDrawn = sal_True;
+ i++;
+ }
+ // #i20085# This is just the other way
+ // around as above. Only difference: mask
+ // is inverted
+ else if ( ( nWinRop == SRCAND ) && ( pSave2->nWinRop == SRCPAINT ) )
+ {
+ Bitmap aMask( pSave->aBmp );
+ BitmapEx aBmpEx( pSave2->aBmp, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ bDrawn = sal_True;
+ i++;
+ }
+ }
+ }
+ }
+
+ if ( !bDrawn )
+ {
+ Push();
+ sal_uInt32 nOldRop = SetRasterOp( R2_COPYPEN );
+ Bitmap aBitmap( pSave->aBmp );
+ sal_uInt32 nOperation = ( nRasterOperation & 0xf );
+ switch( nOperation )
+ {
+ case 0x1 :
+ case 0xe :
+ {
+ SetRasterOp( R2_XORPEN );
+ ImplDrawBitmap( aPos, aSize, aBitmap );
+ SetRasterOp( R2_COPYPEN );
+ Bitmap aMask( aBitmap );
+ aMask.Invert();
+ BitmapEx aBmpEx( aBitmap, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ if ( nOperation == 0x1 )
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ }
+ break;
+ case 0x7 :
+ case 0x8 :
+ {
+ Bitmap aMask( aBitmap );
+ if ( ( nUsed & 1 ) && ( nRasterOperation & 0xb0 ) == 0xb0 ) // pattern used
+ {
+ aBitmap.Convert( BMP_CONVERSION_24BIT );
+ aBitmap.Erase( maFillStyle.aFillColor );
+ }
+ BitmapEx aBmpEx( aBitmap, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ if ( nOperation == 0x7 )
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ }
+ break;
+
+ case 0x4 :
+ case 0xb :
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ SetRasterOp( R2_COPYPEN );
+ Bitmap aMask( aBitmap );
+ aBitmap.Invert();
+ BitmapEx aBmpEx( aBitmap, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ SetRasterOp( R2_XORPEN );
+ ImplDrawBitmap( aPos, aSize, aBitmap );
+ if ( nOperation == 0xb )
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ }
+ break;
+
+ case 0x2 :
+ case 0xd :
+ {
+ Bitmap aMask( aBitmap );
+ aMask.Invert();
+ BitmapEx aBmpEx( aBitmap, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ SetRasterOp( R2_XORPEN );
+ ImplDrawBitmap( aPos, aSize, aBitmap );
+ if ( nOperation == 0xd )
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ }
+ break;
+ case 0x6 :
+ case 0x9 :
+ {
+ SetRasterOp( R2_XORPEN );
+ ImplDrawBitmap( aPos, aSize, aBitmap );
+ if ( nOperation == 0x9 )
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ }
+ break;
+
+ case 0x0 : // WHITENESS
+ case 0xf : // BLACKNESS
+ { // in this case nRasterOperation is either 0 or 0xff
+ maFillStyle = WinMtfFillStyle( Color( nRasterOperation, nRasterOperation, nRasterOperation ) );
+ UpdateFillStyle();
+ DrawRect( aRect, sal_False );
+ }
+ break;
+
+ case 0x3 : // only source is used
+ case 0xc :
+ {
+ if ( nRasterOperation == 0x33 )
+ aBitmap.Invert();
+ ImplDrawBitmap( aPos, aSize, aBitmap );
+ }
+ break;
+
+ case 0x5 : // only destination is used
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ case 0xa : // no operation
+ break;
+ }
+ SetRasterOp( nOldRop );
+ Pop();
+ }
+ }
+ }
+ nObjectsLeft -= nObjectsOfSameSize;
+ }
+
+ for( size_t i = 0, n = rSaveList.size(); i < n; ++i )
+ delete rSaveList[ i ];
+ rSaveList.clear();
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetDevOrg( const Point& rPoint )
+{
+ mnDevOrgX = rPoint.X();
+ mnDevOrgY = rPoint.Y();
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetDevOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
+{
+ mnDevOrgX += nXAdd;
+ mnDevOrgY += nYAdd;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetDevExt( const Size& rSize )
+{
+ if ( rSize.Width() && rSize.Height() )
+ {
+ switch( mnMapMode )
+ {
+ case MM_ISOTROPIC :
+ case MM_ANISOTROPIC :
+ {
+ mnDevWidth = rSize.Width();
+ mnDevHeight = rSize.Height();
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ScaleDevExt( double fX, double fY )
+{
+ mnDevWidth = FRound( mnDevWidth * fX );
+ mnDevHeight = FRound( mnDevHeight * fY );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetWinOrg( const Point& rPoint )
+{
+ mnWinOrgX = rPoint.X();
+ mnWinOrgY = rPoint.Y();
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetWinOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
+{
+ mnWinOrgX += nXAdd;
+ mnWinOrgY += nYAdd;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetWinExt( const Size& rSize )
+{
+
+ if( rSize.Width() && rSize.Height() )
+ {
+ switch( mnMapMode )
+ {
+ case MM_ISOTROPIC :
+ case MM_ANISOTROPIC :
+ {
+ mnWinExtX = rSize.Width();
+ mnWinExtY = rSize.Height();
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ScaleWinExt( double fX, double fY )
+{
+ mnWinExtX = FRound( mnWinExtX * fX );
+ mnWinExtY = FRound( mnWinExtY * fY );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetrclBounds( const Rectangle& rRect )
+{
+ mrclBounds = rRect;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetrclFrame( const Rectangle& rRect )
+{
+ mrclFrame = rRect;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetRefPix( const Size& rSize )
+{
+ mnPixX = rSize.Width();
+ mnPixY = rSize.Height();
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetRefMill( const Size& rSize )
+{
+ mnMillX = rSize.Width();
+ mnMillY = rSize.Height();
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetMapMode( sal_uInt32 nMapMode )
+{
+ mnMapMode = nMapMode;
+ if ( nMapMode == MM_TEXT )
+ {
+ mnWinExtX = mnDevWidth;
+ mnWinExtY = mnDevHeight;
+ }
+ else if ( mnMapMode == MM_HIMETRIC )
+ {
+ mnWinExtX = mnMillX * 100;
+ mnWinExtY = mnMillY * 100;
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetUnitsPerInch( sal_uInt16 nUnitsPerInch )
+{
+ if( nUnitsPerInch != 0 )
+ mnUnitsPerInch = nUnitsPerInch;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetWorldTransform( const XForm& rXForm )
+{
+ maXForm.eM11 = rXForm.eM11;
+ maXForm.eM12 = rXForm.eM12;
+ maXForm.eM21 = rXForm.eM21;
+ maXForm.eM22 = rXForm.eM22;
+ maXForm.eDx = rXForm.eDx;
+ maXForm.eDy = rXForm.eDy;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ModifyWorldTransform( const XForm& rXForm, sal_uInt32 nMode )
+{
+ switch( nMode )
+ {
+ case MWT_IDENTITY :
+ {
+ maXForm.eM11 = maXForm.eM12 = maXForm.eM21 = maXForm.eM22 = 1.0f;
+ maXForm.eDx = maXForm.eDy = 0.0f;
+ }
+ break;
+
+ case MWT_RIGHTMULTIPLY :
+ case MWT_LEFTMULTIPLY :
+ {
+ const XForm* pLeft;
+ const XForm* pRight;
+
+ if ( nMode == MWT_LEFTMULTIPLY )
+ {
+ pLeft = &rXForm;
+ pRight = &maXForm;
+ }
+ else
+ {
+ pLeft = &maXForm;
+ pRight = &rXForm;
+ }
+
+ float aF[3][3];
+ float bF[3][3];
+ float cF[3][3];
+
+ aF[0][0] = pLeft->eM11;
+ aF[0][1] = pLeft->eM12;
+ aF[0][2] = 0;
+ aF[1][0] = pLeft->eM21;
+ aF[1][1] = pLeft->eM22;
+ aF[1][2] = 0;
+ aF[2][0] = pLeft->eDx;
+ aF[2][1] = pLeft->eDy;
+ aF[2][2] = 1;
+
+ bF[0][0] = pRight->eM11;
+ bF[0][1] = pRight->eM12;
+ bF[0][2] = 0;
+ bF[1][0] = pRight->eM21;
+ bF[1][1] = pRight->eM22;
+ bF[1][2] = 0;
+ bF[2][0] = pRight->eDx;
+ bF[2][1] = pRight->eDy;
+ bF[2][2] = 1;
+
+ int i, j, k;
+ for ( i = 0; i < 3; i++ )
+ {
+ for ( j = 0; j < 3; j++ )
+ {
+ cF[i][j] = 0;
+ for ( k = 0; k < 3; k++ )
+ cF[i][j] += aF[i][k] * bF[k][j];
+ }
+ }
+ maXForm.eM11 = cF[0][0];
+ maXForm.eM12 = cF[0][1];
+ maXForm.eM21 = cF[1][0];
+ maXForm.eM22 = cF[1][1];
+ maXForm.eDx = cF[2][0];
+ maXForm.eDy = cF[2][1];
+ }
+ break;
+ }
+ }
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::Push() // !! to be able to access the original ClipRegion it
+{ // is not allowed to use the MetaPushAction()
+ UpdateClipRegion(); // (the original clip region is on top of the stack) (SJ)
+ SaveStructPtr pSave( new SaveStruct );
+
+ pSave->aLineStyle = maLineStyle;
+ pSave->aFillStyle = maFillStyle;
+
+ pSave->aFont = maFont;
+ pSave->aTextColor = maTextColor;
+ pSave->nTextAlign = mnTextAlign;
+ pSave->nTextLayoutMode = mnTextLayoutMode;
+ pSave->nMapMode = mnMapMode;
+ pSave->nGfxMode = mnGfxMode;
+ pSave->nBkMode = mnBkMode;
+ pSave->aBkColor = maBkColor;
+ pSave->bFillStyleSelected = mbFillStyleSelected;
+
+ pSave->aActPos = maActPos;
+ pSave->aXForm = maXForm;
+ pSave->eRasterOp = meRasterOp;
+
+ pSave->nWinOrgX = mnWinOrgX;
+ pSave->nWinOrgY = mnWinOrgY;
+ pSave->nWinExtX = mnWinExtX;
+ pSave->nWinExtY = mnWinExtY;
+ pSave->nDevOrgX = mnDevOrgX;
+ pSave->nDevOrgY = mnDevOrgY;
+ pSave->nDevWidth = mnDevWidth;
+ pSave->nDevHeight = mnDevHeight;
+
+ pSave->aPathObj = aPathObj;
+ pSave->aClipPath = aClipPath;
+
+ vSaveStack.push_back( pSave );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::Pop()
+{
+ // Die aktuellen Daten vom Stack holen
+ if( !vSaveStack.empty() )
+ {
+ // Die aktuelle Daten auf dem Stack sichern
+ SaveStructPtr pSave( vSaveStack.back() );
+
+ maLineStyle = pSave->aLineStyle;
+ maFillStyle = pSave->aFillStyle;
+
+ maFont = pSave->aFont;
+ maTextColor = pSave->aTextColor;
+ mnTextAlign = pSave->nTextAlign;
+ mnTextLayoutMode = pSave->nTextLayoutMode;
+ mnBkMode = pSave->nBkMode;
+ mnGfxMode = pSave->nGfxMode;
+ mnMapMode = pSave->nMapMode;
+ maBkColor = pSave->aBkColor;
+ mbFillStyleSelected = pSave->bFillStyleSelected;
+
+ maActPos = pSave->aActPos;
+ maXForm = pSave->aXForm;
+ meRasterOp = pSave->eRasterOp;
+
+ mnWinOrgX = pSave->nWinOrgX;
+ mnWinOrgY = pSave->nWinOrgY;
+ mnWinExtX = pSave->nWinExtX;
+ mnWinExtY = pSave->nWinExtY;
+ mnDevOrgX = pSave->nDevOrgX;
+ mnDevOrgY = pSave->nDevOrgY;
+ mnDevWidth = pSave->nDevWidth;
+ mnDevHeight = pSave->nDevHeight;
+
+ aPathObj = pSave->aPathObj;
+ if ( ! ( aClipPath == pSave->aClipPath ) )
+ {
+ aClipPath = pSave->aClipPath;
+ mbClipNeedsUpdate = true;
+ }
+ if ( meLatestRasterOp != meRasterOp )
+ mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
+ vSaveStack.pop_back();
+ }
+}
+
+void WinMtfOutput::AddFromGDIMetaFile( GDIMetaFile& rGDIMetaFile )
+{
+ rGDIMetaFile.Play( *mpGDIMetaFile, 0xFFFFFFFF );
+}
+
+void WinMtfOutput::PassEMFPlusHeaderInfo()
+{
+ EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS header info\n"));
+
+ SvMemoryStream mem;
+ sal_Int32 nLeft, nRight, nTop, nBottom;
+
+ nLeft = mrclFrame.Left();
+ nTop = mrclFrame.Top();
+ nRight = mrclFrame.Right();
+ nBottom = mrclFrame.Bottom();
+
+ // emf header info
+ mem << nLeft << nTop << nRight << nBottom;
+ mem << mnPixX << mnPixY << mnMillX << mnMillY;
+
+ float one, zero;
+
+ one = 1;
+ zero = 0;
+
+ // add transformation matrix to be used in vcl's metaact.cxx for
+ // rotate and scale operations
+ mem << one << zero << zero << one << zero << zero;
+
+ // need to flush the stream, otherwise GetEndOfData will return 0
+ // on windows where the function parameters are probably resolved in reverse order
+ mem.Flush();
+
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS_HEADER_INFO", 0, (const sal_uInt8*) mem.GetData(), mem.GetEndOfData() ) );
+ mpGDIMetaFile->UseCanvas( sal_True );
+}
+
+void WinMtfOutput::PassEMFPlus( void* pBuffer, sal_uInt32 nLength )
+{
+ EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS comment length %04x\n",(unsigned int) nLength));
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS", 0, static_cast<const sal_uInt8*>(pBuffer), nLength ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/winmtf.hxx b/vcl/source/filter/wmf/winmtf.hxx
new file mode 100644
index 000000000000..bc368e6e6baa
--- /dev/null
+++ b/vcl/source/filter/wmf/winmtf.hxx
@@ -0,0 +1,890 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#ifndef _WINMTF_HXX
+#define _WINMTF_HXX
+
+#ifdef DBG_UTIL
+#define WIN_MTF_ASSERT
+#endif
+
+#include <sot/object.hxx>
+#include <boost/shared_ptr.hpp>
+#include <vcl/graph.hxx>
+#include <vcl/virdev.hxx>
+#include <basegfx/tools/b2dclipstate.hxx>
+#include <vcl/font.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/lineinfo.hxx>
+#include <svtools/fltcall.hxx>
+
+#define ERROR 0
+#define NULLREGION 1
+#define SIMPLEREGION 2
+#define COMPLEXREGION 3
+
+#define RGN_AND 1
+#define RGN_OR 2
+#define RGN_XOR 3
+#define RGN_DIFF 4
+#define RGN_COPY 5
+
+#define TRANSPARENT 1
+#define OPAQUE 2
+#define BKMODE_LAST 2
+
+/* xform stuff */
+#define MWT_IDENTITY 1
+#define MWT_LEFTMULTIPLY 2
+#define MWT_RIGHTMULTIPLY 3
+
+#define ENHMETA_STOCK_OBJECT 0x80000000
+
+/* Stock Logical Objects */
+#define WHITE_BRUSH 0
+#define LTGRAY_BRUSH 1
+#define GRAY_BRUSH 2
+#define DKGRAY_BRUSH 3
+#define BLACK_BRUSH 4
+#define NULL_BRUSH 5
+#define HOLLOW_BRUSH NULL_BRUSH
+#define WHITE_PEN 6
+#define BLACK_PEN 7
+#define NULL_PEN 8
+#define OEM_FIXED_FONT 10
+#define ANSI_FIXED_FONT 11
+#define ANSI_VAR_FONT 12
+#define SYSTEM_FONT 13
+#define DEVICE_DEFAULT_FONT 14
+#define DEFAULT_PALETTE 15
+#define SYSTEM_FIXED_FONT 16
+
+
+#define R2_BLACK 1
+#define R2_NOTMERGEPEN 2
+#define R2_MASKNOTPEN 3
+#define R2_NOTCOPYPEN 4
+#define R2_MASKPENNOT 5
+#define R2_NOT 6
+#define R2_XORPEN 7
+#define R2_NOTMASKPEN 8
+#define R2_MASKPEN 9
+#define R2_NOTXORPEN 10
+#define R2_NOP 11
+#define R2_MERGENOTPEN 12
+#define R2_COPYPEN 13
+#define R2_MERGEPENNOT 14
+#define R2_MERGEPEN 15
+#define R2_WHITE 16
+
+/* Mapping Modes */
+#define MM_TEXT 1
+#define MM_LOMETRIC 2
+#define MM_HIMETRIC 3
+#define MM_LOENGLISH 4
+#define MM_HIENGLISH 5
+#define MM_TWIPS 6
+#define MM_ISOTROPIC 7
+#define MM_ANISOTROPIC 8
+
+
+/* Graphics Modes */
+#define GM_COMPATIBLE 1
+#define GM_ADVANCED 2
+#define GM_LAST 2
+
+/* StretchBlt() Modes */
+#define BLACKONWHITE 1
+#define WHITEONBLACK 2
+#define COLORONCOLOR 3
+#define HALFTONE 4
+#define MAXSTRETCHBLTMODE 4
+#define STRETCH_ANDSCANS BLACKONWHITE
+#define STRETCH_ORSCANS WHITEONBLACK
+#define STRETCH_DELETESCANS COLORONCOLOR
+#define STRETCH_HALFTONE HALFTONE
+
+#define LF_FACESIZE 32
+
+struct LOGFONTW
+{
+ sal_Int32 lfHeight;
+ sal_Int32 lfWidth;
+ sal_Int32 lfEscapement;
+ sal_Int32 lfOrientation;
+ sal_Int32 lfWeight;
+ sal_uInt8 lfItalic;
+ sal_uInt8 lfUnderline;
+ sal_uInt8 lfStrikeOut;
+ sal_uInt8 lfCharSet;
+ sal_uInt8 lfOutPrecision;
+ sal_uInt8 lfClipPrecision;
+ sal_uInt8 lfQuality;
+ sal_uInt8 lfPitchAndFamily;
+ String alfFaceName;
+};
+struct WMF_EXTERNALHEADER;
+
+#define TA_NOUPDATECP 0x0000
+#define TA_UPDATECP 0x0001
+#define TA_LEFT 0x0000
+#define TA_RIGHT 0x0002
+#define TA_CENTER 0x0006
+#define TA_RIGHT_CENTER (TA_RIGHT | TA_CENTER)
+#define TA_TOP 0x0000
+#define TA_BOTTOM 0x0008
+#define TA_BASELINE 0x0018
+
+#define SRCCOPY 0x00CC0020L
+#define SRCPAINT 0x00EE0086L
+#define SRCAND 0x008800C6L
+#define SRCINVERT 0x00660046L
+#define SRCERASE 0x00440328L
+#define NOTSRCCOPY 0x00330008L
+#define NOTSRCERASE 0x001100A6L
+#define MERGECOPY 0x00C000CAL
+#define MERGEPAINT 0x00BB0226L
+#define PATCOPY 0x00F00021L
+#define PATPAINT 0x00FB0A09L
+#define PATINVERT 0x005A0049L
+#define DSTINVERT 0x00550009L
+#define BLACKNESS 0x00000042L
+#define WHITENESS 0x00FF0062L
+
+#define PS_SOLID 0
+#define PS_DASH 1
+#define PS_DOT 2
+#define PS_DASHDOT 3
+#define PS_DASHDOTDOT 4
+#define PS_NULL 5
+#define PS_INSIDEFRAME 6
+#define PS_USERSTYLE 7
+#define PS_ALTERNATE 8
+#define PS_STYLE_MASK 15
+
+#define PS_ENDCAP_ROUND 0x000
+#define PS_ENDCAP_SQUARE 0x100
+#define PS_ENDCAP_FLAT 0x200
+#define PS_ENDCAP_MASK 0xF00
+
+#define PS_JOIN_ROUND 0x0000
+#define PS_JOIN_BEVEL 0x1000
+#define PS_JOIN_MITER 0x2000
+#define PS_JOIN_MASK 0xF000
+
+#define PS_COSMETIC 0x00000
+#define PS_GEOMETRIC 0x10000
+#define PS_TYPE_MASK 0xF0000
+
+#define ANSI_CHARSET 0
+#define DEFAULT_CHARSET 1
+#define SYMBOL_CHARSET 2
+#define SHIFTJIS_CHARSET 128
+#define HANGEUL_CHARSET 129
+#define GB2312_CHARSET 134
+#define CHINESEBIG5_CHARSET 136
+#define OEM_CHARSET 255
+/*WINVER >= 0x0400*/
+#define JOHAB_CHARSET 130
+#define HEBREW_CHARSET 177
+#define ARABIC_CHARSET 178
+#define GREEK_CHARSET 161
+#define TURKISH_CHARSET 162
+#define VIETNAMESE_CHARSET 163
+#define THAI_CHARSET 222
+#define EASTEUROPE_CHARSET 238
+#define RUSSIAN_CHARSET 204
+#define MAC_CHARSET 77
+#define BALTIC_CHARSET 186
+
+#define ETO_OPAQUE 0x0002
+#define ETO_CLIPPED 0x0004
+/*WINVER >= 0x0400*/
+#define ETO_GLYPH_INDEX 0x0010
+#define ETO_RTLREADING 0x0080
+#define ETO_NUMERICSLOCAL 0x0400
+#define ETO_NUMERICSLATIN 0x0800
+#define ETO_IGNORELANGUAGE 0x1000
+/*_WIN32_WINNT >= 0x0500*/
+#define ETO_PDY 0x2000
+
+
+#define DEFAULT_PITCH 0x00
+#define FIXED_PITCH 0x01
+#define VARIABLE_PITCH 0x02
+
+/* Font Families */
+#define FF_DONTCARE 0x00
+#define FF_ROMAN 0x10
+#define FF_SWISS 0x20
+#define FF_MODERN 0x30
+#define FF_SCRIPT 0x40
+#define FF_DECORATIVE 0x50
+
+#define FW_DONTCARE 0
+#define FW_THIN 100
+#define FW_EXTRALIGHT 200
+#define FW_LIGHT 300
+#define FW_NORMAL 400
+#define FW_MEDIUM 500
+#define FW_SEMIBOLD 600
+#define FW_BOLD 700
+#define FW_EXTRABOLD 800
+#define FW_HEAVY 900
+#define FW_ULTRALIGHT 200
+#define FW_REGULAR 400
+#define FW_DEMIBOLD 600
+#define FW_ULTRABOLD 800
+#define FW_BLACK 900
+
+#define BS_SOLID 0
+#define BS_NULL 1
+#define BS_HOLLOW 1
+#define BS_HATCHED 2
+#define BS_PATTERN 3
+#define BS_INDEXED 4
+#define BS_DIBPATTERN 5
+#define BS_DIBPATTERNPT 6
+#define BS_PATTERN8X8 7
+#define BS_DIBPATTERN8X8 8
+#define BS_MONOPATTERN 9
+
+#define W_HS_HORIZONTAL 0
+#define W_HS_VERTICAL 1
+#define W_HS_FDIAGONAL 2
+#define W_HS_BDIAGONAL 3
+#define W_HS_CROSS 4
+#define W_HS_DIAGCROSS 5
+
+#define RDH_RECTANGLES 1
+
+#define W_MFCOMMENT 15
+
+#define PRIVATE_ESCAPE_UNICODE 2
+
+//============================ WMFReader ==================================
+
+#ifdef WIN_MTF_ASSERT
+#define WIN_MTF_ASSERT_INIT 0x80000000
+#define WIN_MTF_ASSERT_ONCE 0x40000000
+#define WIN_MTF_ASSERT_MIFE 0x20000000
+
+void WinMtfAssertHandler( const sal_Char*, sal_uInt32 nFlags = WIN_MTF_ASSERT_MIFE );
+#endif
+
+class WinMtfClipPath
+{
+ basegfx::tools::B2DClipState maClip;
+
+public :
+ WinMtfClipPath(): maClip() {};
+
+ void setClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode );
+ void intersectClipRect( const Rectangle& rRect );
+ void excludeClipRect( const Rectangle& rRect );
+ void moveClipRegion( const Size& rSize );
+
+ bool isEmpty() const { return maClip.isCleared(); }
+
+ basegfx::B2DPolyPolygon getClipPath() const;
+
+ bool operator==( const WinMtfClipPath& rPath ) const
+ {
+ return maClip == rPath.maClip;
+ };
+};
+
+class WinMtfPathObj : public PolyPolygon
+{
+ sal_Bool bClosed;
+
+public :
+
+ WinMtfPathObj() { bClosed = sal_True; }
+ void Init() { Clear(); bClosed = sal_True; };
+ void ClosePath();
+ void AddPoint( const Point& rPoint );
+ void AddPolygon( const Polygon& rPoly );
+ void AddPolyLine( const Polygon& rPoly );
+ void AddPolyPolygon( const PolyPolygon& rPolyPolygon );
+};
+
+struct WinMtfFontStyle
+{
+ Font aFont;
+
+ WinMtfFontStyle( LOGFONTW& rLogFont );
+};
+
+// -----------------------------------------------------------------------------
+
+typedef enum {
+ FillStyleSolid,
+ FillStylePattern
+} WinMtfFillStyleType;
+
+struct WinMtfFillStyle
+{
+ Color aFillColor;
+ sal_Bool bTransparent;
+ WinMtfFillStyleType aType;
+ Bitmap aBmp;
+
+ WinMtfFillStyle()
+ : aFillColor(Color(COL_BLACK))
+ , bTransparent(sal_False)
+ , aType(FillStyleSolid)
+ {
+ }
+
+ WinMtfFillStyle( const Color& rColor, sal_Bool bTrans = sal_False )
+ : aFillColor(rColor)
+ , bTransparent(bTrans)
+ , aType(FillStyleSolid)
+ {
+ }
+
+ WinMtfFillStyle(Bitmap& rBmp)
+ : aType(FillStylePattern)
+ , aBmp(rBmp)
+ {
+ }
+
+ sal_Bool operator==( const WinMtfFillStyle& rStyle )
+ {
+ return ( ( aFillColor == rStyle.aFillColor )
+ && ( bTransparent == rStyle.bTransparent )
+ && ( aType == rStyle.aType )
+ );
+ }
+ sal_Bool operator==( WinMtfFillStyle* pStyle )
+ {
+ return ( ( aFillColor == pStyle->aFillColor )
+ && ( bTransparent == pStyle->bTransparent )
+ && ( aType == pStyle->aType )
+ );
+ }
+ WinMtfFillStyle& operator=( const WinMtfFillStyle& rStyle )
+ {
+ aFillColor = rStyle.aFillColor;
+ bTransparent = rStyle.bTransparent;
+ aBmp = rStyle.aBmp;
+ aType = rStyle.aType;
+ return *this;
+ }
+ WinMtfFillStyle& operator=( WinMtfFillStyle* pStyle )
+ {
+ aFillColor = pStyle->aFillColor;
+ bTransparent = pStyle->bTransparent;
+ aBmp = pStyle->aBmp;
+ aType = pStyle->aType;
+ return *this;
+ }
+};
+
+// -----------------------------------------------------------------------------
+
+struct WinMtfLineStyle
+{
+ Color aLineColor;
+ LineInfo aLineInfo;
+ sal_Bool bTransparent;
+
+ WinMtfLineStyle() :
+ aLineColor ( COL_BLACK ),
+ bTransparent( sal_False ) {}
+
+ WinMtfLineStyle( const Color& rColor, sal_Bool bTrans = sal_False ) :
+ aLineColor ( rColor ),
+ bTransparent( bTrans ) {}
+
+ WinMtfLineStyle( const Color& rColor, const LineInfo& rStyle, sal_Bool bTrans = sal_False ) :
+ aLineColor ( rColor ),
+ aLineInfo ( rStyle ),
+ bTransparent( bTrans ) {}
+
+ sal_Bool operator==( const WinMtfLineStyle& rStyle )
+ {
+ return ( ( aLineColor == rStyle.aLineColor )
+ && ( bTransparent == rStyle.bTransparent )
+ && ( aLineInfo == rStyle.aLineInfo )
+ );
+ }
+ sal_Bool operator==( WinMtfLineStyle* pStyle )
+ {
+ return ( ( aLineColor == pStyle->aLineColor )
+ && ( bTransparent == pStyle->bTransparent )
+ && ( aLineInfo == pStyle->aLineInfo )
+ );
+ }
+ WinMtfLineStyle& operator=( const WinMtfLineStyle& rStyle )
+ {
+ aLineColor = rStyle.aLineColor;
+ bTransparent = rStyle.bTransparent;
+ aLineInfo = rStyle.aLineInfo;
+ return *this;
+ }
+
+ WinMtfLineStyle& operator=( WinMtfLineStyle* pStyle )
+ {
+ aLineColor = pStyle->aLineColor;
+ bTransparent = pStyle->bTransparent;
+ aLineInfo = pStyle->aLineInfo;
+ return *this;
+ }
+};
+
+// -----------------------------------------------------------------------------
+
+struct XForm
+{
+ float eM11;
+ float eM12;
+ float eM21;
+ float eM22;
+ float eDx;
+ float eDy;
+ XForm()
+ {
+ eM11 = eM22 = 1.0f;
+ eDx = eDy = eM12 = eM21 = 0.0f;
+ }
+
+ friend SvStream& operator>>( SvStream& rIn, XForm& rXForm );
+};
+
+// -----------------------------------------------------------------------------
+
+struct SaveStruct
+{
+ sal_uInt32 nBkMode, nMapMode, nGfxMode, nTextLayoutMode;
+ sal_Int32 nWinOrgX, nWinOrgY, nWinExtX, nWinExtY;
+ sal_Int32 nDevOrgX, nDevOrgY, nDevWidth, nDevHeight;
+
+ WinMtfLineStyle aLineStyle;
+ WinMtfFillStyle aFillStyle;
+
+ Font aFont;
+ Color aBkColor;
+ Color aTextColor;
+ sal_uInt32 nTextAlign;
+ RasterOp eRasterOp;
+
+ Point aActPos;
+ WinMtfPathObj aPathObj;
+ WinMtfClipPath aClipPath;
+ XForm aXForm;
+
+ sal_Bool bRecordPath;
+ sal_Bool bFillStyleSelected;
+};
+
+typedef ::boost::shared_ptr< SaveStruct > SaveStructPtr;
+
+// -----------------------------------------------------------------------------
+
+struct BSaveStruct
+{
+ Bitmap aBmp;
+ Rectangle aOutRect;
+ sal_uInt32 nWinRop;
+ WinMtfFillStyle aStyle;
+
+ BSaveStruct(
+ const Bitmap& rBmp,
+ const Rectangle& rOutRect,
+ sal_uInt32 nRop,
+ WinMtfFillStyle& rStyle
+ )
+ : aBmp( rBmp )
+ , aOutRect( rOutRect )
+ , nWinRop( nRop )
+ , aStyle ( rStyle )
+ {}
+};
+
+typedef ::std::vector< BSaveStruct* > BSaveStructList_impl;
+
+// -----------------------------------------------------------------------------
+
+enum GDIObjectType {
+ GDI_DUMMY = 0,
+ GDI_PEN = 1,
+ GDI_BRUSH = 2,
+ GDI_FONT = 3,
+ GDI_PALETTE = 4,
+ GDI_BITMAP = 5,
+ GDI_REGION = 6
+};
+
+struct GDIObj
+{
+ void* pStyle;
+ GDIObjectType eType;
+
+ GDIObj() :
+ pStyle ( NULL ),
+ eType ( GDI_DUMMY )
+ {
+ }
+
+ GDIObj( GDIObjectType eT, void* pS ) { pStyle = pS; eType = eT; }
+ void Set( GDIObjectType eT, void* pS ) { pStyle = pS; eType = eT; }
+ void Delete()
+ {
+ if ( pStyle )
+ {
+ switch ( eType )
+ {
+ case GDI_PEN :
+ delete (WinMtfLineStyle*)pStyle;
+ break;
+ case GDI_BRUSH :
+ delete (WinMtfFillStyle*)pStyle;
+ break;
+ case GDI_FONT :
+ delete (WinMtfFontStyle*)pStyle;
+ break;
+
+ default:
+ OSL_FAIL( "unsupported style deleted" );
+ break;
+ }
+ pStyle = NULL;
+ }
+ }
+
+ ~GDIObj()
+ {
+ Delete();
+ }
+};
+
+// -----------------------------------------------------------------------------
+
+class WinMtfOutput
+{
+
+ WinMtfPathObj aPathObj;
+ WinMtfClipPath aClipPath;
+
+ WinMtfLineStyle maLatestLineStyle;
+ WinMtfLineStyle maLineStyle;
+ WinMtfFillStyle maLatestFillStyle;
+ WinMtfFillStyle maFillStyle;
+ Font maLatestFont;
+ Font maFont;
+ sal_uInt32 mnLatestTextAlign;
+ sal_uInt32 mnTextAlign;
+ Color maLatestTextColor;
+ Color maTextColor;
+ Color maLatestBkColor;
+ Color maBkColor;
+ sal_uInt32 mnLatestTextLayoutMode;
+ sal_uInt32 mnTextLayoutMode;
+ sal_uInt32 mnLatestBkMode;
+ sal_uInt32 mnBkMode;
+ RasterOp meLatestRasterOp;
+ RasterOp meRasterOp;
+
+ std::vector< GDIObj* > vGDIObj;
+
+ Point maActPos;
+
+ sal_uInt32 mnRop;
+ sal_Bool mbNopMode;
+ sal_Bool mbFillStyleSelected;
+ sal_Bool mbClipNeedsUpdate;
+ sal_Bool mbComplexClip;
+
+ std::vector< SaveStructPtr > vSaveStack;
+
+ sal_uInt32 mnGfxMode;
+ sal_uInt32 mnMapMode;
+ sal_uInt16 mnUnitsPerInch;
+
+ XForm maXForm;
+ sal_Int32 mnDevOrgX, mnDevOrgY;
+ sal_Int32 mnDevWidth, mnDevHeight;
+ sal_Int32 mnWinOrgX, mnWinOrgY; // aktuelles Window-Origin
+ sal_Int32 mnWinExtX, mnWinExtY; // aktuelles Window-Extent
+
+ sal_Int32 mnPixX, mnPixY; // Reference Device in pixel
+ sal_Int32 mnMillX, mnMillY; // Reference Device in Mill
+ Rectangle mrclFrame; // rectangle in logical units 1/100th mm
+ Rectangle mrclBounds;
+
+ GDIMetaFile* mpGDIMetaFile;
+
+ void UpdateLineStyle();
+ void UpdateFillStyle();
+
+ Point ImplMap( const Point& rPt );
+ Size ImplMap( const Size& rSz );
+ Rectangle ImplMap( const Rectangle& rRectangle );
+ void ImplMap( Font& rFont );
+ Polygon& ImplMap( Polygon& rPolygon );
+ PolyPolygon& ImplMap( PolyPolygon& rPolyPolygon );
+ void ImplResizeObjectArry( sal_uInt32 nNewEntry );
+ void ImplSetNonPersistentLineColorTransparenz();
+ void ImplDrawClippedPolyPolygon( const PolyPolygon& rPolyPoly );
+ void ImplDrawBitmap( const Point& rPos, const Size& rSize, const BitmapEx rBitmap );
+
+public:
+
+ void SetDevOrg( const Point& rPoint );
+ void SetDevOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd );
+ void SetDevExt( const Size& rSize );
+ void ScaleDevExt( double fX, double fY );
+
+ void SetWinOrg( const Point& rPoint );
+ void SetWinOrgOffset( sal_Int32 nX, sal_Int32 nY );
+ void SetWinExt( const Size& rSize );
+ void ScaleWinExt( double fX, double fY );
+
+ void SetrclBounds( const Rectangle& rRect );
+ void SetrclFrame( const Rectangle& rRect );
+ void SetRefPix( const Size& rSize );
+ void SetRefMill( const Size& rSize );
+
+ sal_uInt32 GetMapMode() const { return mnMapMode; };
+ void SetMapMode( sal_uInt32 mnMapMode );
+ void SetUnitsPerInch( sal_uInt16 nUnitsPerInch );
+ void SetWorldTransform( const XForm& rXForm );
+ void ModifyWorldTransform( const XForm& rXForm, sal_uInt32 nMode );
+
+ void Push();
+ void Pop();
+
+ sal_uInt32 SetRasterOp( sal_uInt32 nRasterOp );
+ void StrokeAndFillPath( sal_Bool bStroke, sal_Bool bFill );
+
+ void SetGfxMode( sal_Int32 nGfxMode ){ mnGfxMode = nGfxMode; };
+ sal_Int32 GetGfxMode() const { return mnGfxMode; };
+ void SetBkMode( sal_uInt32 nMode );
+ void SetBkColor( const Color& rColor );
+ void SetTextColor( const Color& rColor );
+ void SetTextAlign( sal_uInt32 nAlign );
+ void CreateObject( GDIObjectType, void* pStyle = NULL );
+ void CreateObject( sal_Int32 nIndex, GDIObjectType, void* pStyle = NULL );
+ void DeleteObject( sal_Int32 nIndex );
+ void SelectObject( sal_Int32 nIndex );
+ CharSet GetCharSet(){ return maFont.GetCharSet(); };
+ WinMtfFillStyle& GetFillStyle () { return maFillStyle; }
+ const Font& GetFont() const;
+ void SetTextLayoutMode( const sal_uInt32 nLayoutMode );
+
+ void ClearPath(){ aPathObj.Init(); };
+ void ClosePath(){ aPathObj.ClosePath(); };
+ const PolyPolygon& GetPathObj(){ return aPathObj; };
+
+ void MoveTo( const Point& rPoint, sal_Bool bRecordPath = sal_False );
+ void LineTo( const Point& rPoint, sal_Bool bRecordPath = sal_False );
+ void DrawPixel( const Point& rSource, const Color& rColor );
+ void DrawRect( const Rectangle& rRect, sal_Bool bEdge = sal_True );
+ void DrawRoundRect( const Rectangle& rRect, const Size& rSize );
+ void DrawEllipse( const Rectangle& rRect );
+ void DrawArc(
+ const Rectangle& rRect,
+ const Point& rStartAngle,
+ const Point& rEndAngle,
+ sal_Bool bDrawTo = sal_False
+ );
+ void DrawPie(
+ const Rectangle& rRect,
+ const Point& rStartAngle,
+ const Point& rEndAngle
+ );
+ void DrawChord(
+ const Rectangle& rRect,
+ const Point& rStartAngle,
+ const Point& rEndAngle
+ );
+ void DrawPolygon( Polygon& rPolygon, sal_Bool bRecordPath = sal_False );
+ void DrawPolygon( Polygon& rPolygon, sal_Bool /*bDrawTo*/, sal_Bool bRecordPath)
+ {
+ //For ReadAndDrawPolygon template compatibility
+ DrawPolygon(rPolygon, bRecordPath);
+ }
+ void DrawPolyPolygon( PolyPolygon& rPolyPolygon, sal_Bool bRecordPath = sal_False );
+ void DrawPolyLine(
+ Polygon& rPolygon,
+ sal_Bool bDrawTo = sal_False,
+ sal_Bool bRecordPath = sal_False
+ );
+ void DrawPolyBezier(
+ Polygon& rPolygin,
+ sal_Bool bDrawTo = sal_False,
+ sal_Bool bRecordPath = sal_False
+ );
+ void DrawText(
+ Point& rPosition,
+ String& rString,
+ sal_Int32* pDXArry = NULL,
+ sal_Bool bRecordPath = sal_False,
+ sal_Int32 nGraphicsMode = GM_COMPATIBLE
+ );
+ void ResolveBitmapActions( BSaveStructList_impl& rSaveList );
+
+ void IntersectClipRect( const Rectangle& rRect );
+ void ExcludeClipRect( const Rectangle& rRect );
+ void MoveClipRegion( const Size& rSize );
+ void SetClipPath(
+ const PolyPolygon& rPolyPoly,
+ sal_Int32 nClippingMode,
+ sal_Bool bIsMapped
+ );
+ void UpdateClipRegion();
+ void AddFromGDIMetaFile( GDIMetaFile& rGDIMetaFile );
+
+ void PassEMFPlus( void* pBuffer, sal_uInt32 nLength );
+ void PassEMFPlusHeaderInfo();
+
+ WinMtfOutput( GDIMetaFile& rGDIMetaFile );
+ virtual ~WinMtfOutput();
+};
+
+// -----------------------------------------------------------------------------
+
+class WinMtf
+{
+protected:
+
+ WinMtfOutput* pOut;
+ SvStream* pWMF; // Die einzulesende WMF/EMF-Datei
+
+ sal_uInt32 nStartPos, nEndPos;
+ BSaveStructList_impl aBmpSaveList;
+
+ FilterConfigItem* pFilterConfigItem;
+
+ com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
+
+ // Sorgt dafuer, das aSampledBrush der aktuelle Brush des GDIMetaFiles ist.
+
+ Color ReadColor();
+ void Callback( sal_uInt16 nPercent );
+
+ WinMtf(
+ WinMtfOutput* pOut,
+ SvStream& rStreamWMF,
+ FilterConfigItem* pConfigItem = NULL
+ );
+ ~WinMtf();
+};
+
+//============================ EMFReader ==================================
+
+class EnhWMFReader : public WinMtf
+{
+ sal_Bool bRecordPath;
+ sal_Int32 nRecordCount;
+ sal_Bool bEMFPlus;
+
+
+ sal_Bool ReadHeader();
+ // Liesst und konvertiert ein Rechteck
+ Rectangle ReadRectangle( sal_Int32, sal_Int32, sal_Int32, sal_Int32 );
+ void ImplExtTextOut( sal_Bool bWideCharakter );
+
+public:
+ EnhWMFReader(
+ SvStream& rStreamWMF,
+ GDIMetaFile& rGDIMetaFile,
+ FilterConfigItem* pConfigItem = NULL
+ )
+ : WinMtf( new WinMtfOutput( rGDIMetaFile )
+ , rStreamWMF
+ , pConfigItem )
+ , bRecordPath( sal_False )
+ , bEMFPlus( sal_False )
+ {};
+ ~EnhWMFReader();
+
+ sal_Bool ReadEnhWMF();
+ void ReadEMFPlusComment(sal_uInt32 length, sal_Bool& bHaveDC);
+private:
+ template <class T> void ReadAndDrawPolyPolygon();
+ template <class T> void ReadAndDrawPolyLine();
+ template <class T> Polygon ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints);
+ template <class T, class Drawer> void ReadAndDrawPolygon(Drawer drawer, const sal_Bool skipFirst);
+};
+
+//============================ WMFReader ==================================
+
+class WMFReader : public WinMtf
+{
+private:
+
+ VirtualDevice aVDev; // just for the purpose of "IsFontAvailable"
+ sal_uInt16 nUnitsPerInch;
+ sal_uInt32 nRecSize;
+
+ // embedded EMF data
+ SvMemoryStream* pEMFStream;
+
+ // total number of comment records containing EMF data
+ sal_uInt32 nEMFRecCount;
+
+ // number of EMF records read
+ sal_uInt32 nEMFRec;
+
+ // total size of embedded EMF data
+ sal_uInt32 nEMFSize;
+
+ sal_uInt32 nSkipActions;
+ sal_uInt32 nCurrentAction;
+ sal_uInt32 nUnicodeEscapeAction;
+
+ WMF_EXTERNALHEADER* pExternalHeader;
+
+ // Liesst den Kopf der WMF-Datei
+ sal_Bool ReadHeader();
+
+ // Liesst die Parameter des Rocords mit der Funktionsnummer nFunction.
+ void ReadRecordParams( sal_uInt16 nFunction );
+
+ Point ReadPoint(); // Liesst und konvertiert einen Punkt (erst X dann Y)
+ Point ReadYX(); // Liesst und konvertiert einen Punkt (erst Y dann X)
+ Rectangle ReadRectangle(); // Liesst und konvertiert ein Rechteck
+ Size ReadYXExt();
+ sal_Bool GetPlaceableBound( Rectangle& rSize, SvStream* pStrm );
+
+public:
+
+ WMFReader(
+ SvStream& rStreamWMF,
+ GDIMetaFile& rGDIMetaFile,
+ FilterConfigItem* pConfigItem = NULL,
+ WMF_EXTERNALHEADER* pExtHeader = NULL
+ )
+ : WinMtf( new WinMtfOutput( rGDIMetaFile ), rStreamWMF, pConfigItem )
+ , pEMFStream(NULL),
+ pExternalHeader(pExtHeader)
+ {}
+
+ ~WMFReader();
+
+ // Liesst aus dem Stream eine WMF-Datei und fuellt das GDIMetaFile
+ void ReadWMF();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/winwmf.cxx b/vcl/source/filter/wmf/winwmf.cxx
new file mode 100644
index 000000000000..f9f38e09eb92
--- /dev/null
+++ b/vcl/source/filter/wmf/winwmf.cxx
@@ -0,0 +1,1503 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include "winmtf.hxx"
+#include <boost/scoped_array.hpp>
+#include <vcl/gdimtf.hxx>
+#include <svtools/wmf.hxx>
+#include <rtl/crc.h>
+#include <rtl/tencinfo.h>
+#include <osl/endian.h>
+
+//====================== MS-Windows-defines ===============================
+
+#define W_META_SETBKCOLOR 0x0201
+#define W_META_SETBKMODE 0x0102
+#define W_META_SETMAPMODE 0x0103
+#define W_META_SETROP2 0x0104
+#define W_META_SETRELABS 0x0105
+#define W_META_SETPOLYFILLMODE 0x0106
+#define W_META_SETSTRETCHBLTMODE 0x0107
+#define W_META_SETTEXTCHAREXTRA 0x0108
+#define W_META_SETTEXTCOLOR 0x0209
+#define W_META_SETTEXTJUSTIFICATION 0x020A
+#define W_META_SETWINDOWORG 0x020B
+#define W_META_SETWINDOWEXT 0x020C
+#define W_META_SETVIEWPORTORG 0x020D
+#define W_META_SETVIEWPORTEXT 0x020E
+#define W_META_OFFSETWINDOWORG 0x020F
+#define W_META_SCALEWINDOWEXT 0x0410
+#define W_META_OFFSETVIEWPORTORG 0x0211
+#define W_META_SCALEVIEWPORTEXT 0x0412
+#define W_META_LINETO 0x0213
+#define W_META_MOVETO 0x0214
+#define W_META_EXCLUDECLIPRECT 0x0415
+#define W_META_INTERSECTCLIPRECT 0x0416
+#define W_META_ARC 0x0817
+#define W_META_ELLIPSE 0x0418
+#define W_META_FLOODFILL 0x0419
+#define W_META_PIE 0x081A
+#define W_META_RECTANGLE 0x041B
+#define W_META_ROUNDRECT 0x061C
+#define W_META_PATBLT 0x061D
+#define W_META_SAVEDC 0x001E
+#define W_META_SETPIXEL 0x041F
+#define W_META_OFFSETCLIPRGN 0x0220
+#define W_META_TEXTOUT 0x0521
+#define W_META_BITBLT 0x0922
+#define W_META_STRETCHBLT 0x0B23
+#define W_META_POLYGON 0x0324
+#define W_META_POLYLINE 0x0325
+#define W_META_ESCAPE 0x0626
+#define W_META_RESTOREDC 0x0127
+#define W_META_FILLREGION 0x0228
+#define W_META_FRAMEREGION 0x0429
+#define W_META_INVERTREGION 0x012A
+#define W_META_PAINTREGION 0x012B
+#define W_META_SELECTCLIPREGION 0x012C
+#define W_META_SELECTOBJECT 0x012D
+#define W_META_SETTEXTALIGN 0x012E
+#define W_META_DRAWTEXT 0x062F
+#define W_META_CHORD 0x0830
+#define W_META_SETMAPPERFLAGS 0x0231
+#define W_META_EXTTEXTOUT 0x0a32
+#define W_META_SETDIBTODEV 0x0d33
+#define W_META_SELECTPALETTE 0x0234
+#define W_META_REALIZEPALETTE 0x0035
+#define W_META_ANIMATEPALETTE 0x0436
+#define W_META_SETPALENTRIES 0x0037
+#define W_META_POLYPOLYGON 0x0538
+#define W_META_RESIZEPALETTE 0x0139
+#define W_META_DIBBITBLT 0x0940
+#define W_META_DIBSTRETCHBLT 0x0b41
+#define W_META_DIBCREATEPATTERNBRUSH 0x0142
+#define W_META_STRETCHDIB 0x0f43
+#define W_META_EXTFLOODFILL 0x0548
+#define W_META_RESETDC 0x014C
+#define W_META_STARTDOC 0x014D
+#define W_META_STARTPAGE 0x004F
+#define W_META_ENDPAGE 0x0050
+#define W_META_ABORTDOC 0x0052
+#define W_META_ENDDOC 0x005E
+#define W_META_DELETEOBJECT 0x01f0
+#define W_META_CREATEPALETTE 0x00f7
+#define W_META_CREATEBRUSH 0x00F8
+#define W_META_CREATEPATTERNBRUSH 0x01F9
+#define W_META_CREATEPENINDIRECT 0x02FA
+#define W_META_CREATEFONTINDIRECT 0x02FB
+#define W_META_CREATEBRUSHINDIRECT 0x02FC
+#define W_META_CREATEBITMAPINDIRECT 0x02FD
+#define W_META_CREATEBITMAP 0x06FE
+#define W_META_CREATEREGION 0x06FF
+
+static void GetWinExtMax( const Point& rSource, Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
+{
+ Point aSource( rSource );
+ if ( nMapMode == MM_HIMETRIC )
+ aSource.Y() = -rSource.Y();
+ if ( aSource.X() < rPlaceableBound.Left() )
+ rPlaceableBound.Left() = aSource.X();
+ if ( aSource.X() > rPlaceableBound.Right() )
+ rPlaceableBound.Right() = aSource.X();
+ if ( aSource.Y() < rPlaceableBound.Top() )
+ rPlaceableBound.Top() = aSource.Y();
+ if ( aSource.Y() > rPlaceableBound.Bottom() )
+ rPlaceableBound.Bottom() = aSource.Y();
+}
+
+static void GetWinExtMax( const Rectangle& rSource, Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
+{
+ GetWinExtMax( rSource.TopLeft(), rPlaceableBound, nMapMode );
+ GetWinExtMax( rSource.BottomRight(), rPlaceableBound, nMapMode );
+}
+
+//=================== Methods of WMFReader ==============================
+
+inline Point WMFReader::ReadPoint()
+{
+ short nX = 0, nY = 0;
+ *pWMF >> nX >> nY;
+ return Point( nX, nY );
+}
+
+// ------------------------------------------------------------------------
+
+inline Point WMFReader::ReadYX()
+{
+ short nX = 0, nY = 0;
+ *pWMF >> nY >> nX;
+ return Point( nX, nY );
+}
+
+// ------------------------------------------------------------------------
+
+Rectangle WMFReader::ReadRectangle()
+{
+ Point aBR, aTL;
+ aBR = ReadYX();
+ aTL = ReadYX();
+ aBR.X()--;
+ aBR.Y()--;
+ return Rectangle( aTL, aBR );
+}
+
+// ------------------------------------------------------------------------
+
+Size WMFReader::ReadYXExt()
+{
+ short nW=0, nH=0;
+ *pWMF >> nH >> nW;
+ return Size( nW, nH );
+}
+
+// ------------------------------------------------------------------------
+
+void WMFReader::ReadRecordParams( sal_uInt16 nFunc )
+{
+ switch( nFunc )
+ {
+ case W_META_SETBKCOLOR:
+ {
+ pOut->SetBkColor( ReadColor() );
+ }
+ break;
+
+ case W_META_SETBKMODE:
+ {
+ sal_uInt16 nDat = 0;
+ *pWMF >> nDat;
+ pOut->SetBkMode( nDat );
+ }
+ break;
+
+ // !!!
+ case W_META_SETMAPMODE:
+ {
+ sal_Int16 nMapMode = 0;
+ *pWMF >> nMapMode;
+ pOut->SetMapMode( nMapMode );
+ }
+ break;
+
+ case W_META_SETROP2:
+ {
+ sal_uInt16 nROP2 = 0;
+ *pWMF >> nROP2;
+ pOut->SetRasterOp( nROP2 );
+ }
+ break;
+
+ case W_META_SETTEXTCOLOR:
+ {
+ pOut->SetTextColor( ReadColor() );
+ }
+ break;
+
+ case W_META_SETWINDOWORG:
+ {
+ pOut->SetWinOrg( ReadYX() );
+ }
+ break;
+
+ case W_META_SETWINDOWEXT:
+ {
+ short nWidth = 0, nHeight = 0;
+ *pWMF >> nHeight >> nWidth;
+ pOut->SetWinExt( Size( nWidth, nHeight ) );
+ }
+ break;
+
+ case W_META_OFFSETWINDOWORG:
+ {
+ short nXAdd = 0, nYAdd = 0;
+ *pWMF >> nYAdd >> nXAdd;
+ pOut->SetWinOrgOffset( nXAdd, nYAdd );
+ }
+ break;
+
+ case W_META_SCALEWINDOWEXT:
+ {
+ short nXNum = 0, nXDenom = 0, nYNum = 0, nYDenom = 0;
+ *pWMF >> nYDenom >> nYNum >> nXDenom >> nXNum;
+ pOut->ScaleWinExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
+ }
+ break;
+
+ case W_META_SETVIEWPORTORG:
+ case W_META_SETVIEWPORTEXT:
+ break;
+
+ case W_META_OFFSETVIEWPORTORG:
+ {
+ short nXAdd = 0, nYAdd = 0;
+ *pWMF >> nYAdd >> nXAdd;
+ pOut->SetDevOrgOffset( nXAdd, nYAdd );
+ }
+ break;
+
+ case W_META_SCALEVIEWPORTEXT:
+ {
+ short nXNum = 0, nXDenom = 0, nYNum = 0, nYDenom = 0;
+ *pWMF >> nYDenom >> nYNum >> nXDenom >> nXNum;
+ pOut->ScaleDevExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
+ }
+ break;
+
+ case W_META_LINETO:
+ {
+ pOut->LineTo( ReadYX() );
+ }
+ break;
+
+ case W_META_MOVETO:
+ {
+ pOut->MoveTo( ReadYX() );
+ }
+ break;
+
+ case W_META_INTERSECTCLIPRECT:
+ {
+ pOut->IntersectClipRect( ReadRectangle() );
+ }
+ break;
+
+ case W_META_RECTANGLE:
+ {
+ pOut->DrawRect( ReadRectangle() );
+ }
+ break;
+
+ case W_META_ROUNDRECT:
+ {
+ Size aSize( ReadYXExt() );
+ pOut->DrawRoundRect( ReadRectangle(), Size( aSize.Width() / 2, aSize.Height() / 2 ) );
+ }
+ break;
+
+ case W_META_ELLIPSE:
+ {
+ pOut->DrawEllipse( ReadRectangle() );
+ }
+ break;
+
+ case W_META_ARC:
+ {
+ Point aEnd( ReadYX() );
+ Point aStart( ReadYX() );
+ Rectangle aRect( ReadRectangle() );
+ aRect.Justify();
+ pOut->DrawArc( aRect, aStart, aEnd );
+ }
+ break;
+
+ case W_META_PIE:
+ {
+ Point aEnd( ReadYX() );
+ Point aStart( ReadYX() );
+ Rectangle aRect( ReadRectangle() );
+ aRect.Justify();
+
+ // #i73608# OutputDevice deviates from WMF
+ // semantics. start==end means full ellipse here.
+ if( aStart == aEnd )
+ pOut->DrawEllipse( aRect );
+ else
+ pOut->DrawPie( aRect, aStart, aEnd );
+ }
+ break;
+
+ case W_META_CHORD:
+ {
+ Point aEnd( ReadYX() );
+ Point aStart( ReadYX() );
+ Rectangle aRect( ReadRectangle() );
+ aRect.Justify();
+ pOut->DrawChord( aRect, aStart, aEnd );
+ }
+ break;
+
+ case W_META_POLYGON:
+ {
+ sal_uInt16 nPoints = 0;
+ *pWMF >> nPoints;
+ Polygon aPoly( nPoints );
+ for( sal_uInt16 i = 0; i < nPoints; i++ )
+ aPoly[ i ] = ReadPoint();
+ pOut->DrawPolygon( aPoly );
+ }
+ break;
+
+ case W_META_POLYPOLYGON:
+ {
+ bool bRecordOk = true;
+ sal_uInt16 nPoly = 0;
+ Point* pPtAry;
+ // Number of polygons:
+ *pWMF >> nPoly;
+ // Number of points of each polygon. Determine total number of points
+ boost::scoped_array<sal_uInt16> xPolygonPointCounts(new sal_uInt16[nPoly]);
+ sal_uInt16* pnPoints = xPolygonPointCounts.get();
+ sal_uInt16 nPoints = 0;
+ for(sal_uInt16 i = 0; i < nPoly; i++ )
+ {
+ *pWMF >> pnPoints[i];
+
+ if (pnPoints[i] > SAL_MAX_UINT16 - nPoints)
+ {
+ bRecordOk = false;
+ break;
+ }
+
+ nPoints += pnPoints[i];
+ }
+
+ SAL_WARN_IF(!bRecordOk, "svtools.filter", "polypolygon record has more polygons than we can handle");
+
+ bRecordOk &= pWMF->good();
+
+ if (!bRecordOk)
+ {
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ break;
+ }
+
+ // Polygon points are:
+ boost::scoped_array<Point> xPolygonPoints(new Point[nPoints]);
+ pPtAry = xPolygonPoints.get();
+ for (sal_uInt16 i = 0; i < nPoints; i++ )
+ pPtAry[ i ] = ReadPoint();
+
+ bRecordOk &= pWMF->good();
+
+ if (!bRecordOk)
+ {
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ break;
+ }
+
+ // Produce PolyPolygon Actions
+ PolyPolygon aPolyPoly( nPoly, pnPoints, pPtAry );
+ pOut->DrawPolyPolygon( aPolyPoly );
+ }
+ break;
+
+ case W_META_POLYLINE:
+ {
+ sal_uInt16 nPoints = 0;
+ *pWMF >> nPoints;
+ Polygon aPoly( nPoints );
+ for(sal_uInt16 i = 0; i < nPoints; i++ )
+ aPoly[ i ] = ReadPoint();
+ pOut->DrawPolyLine( aPoly );
+ }
+ break;
+
+ case W_META_SAVEDC:
+ {
+ pOut->Push();
+ }
+ break;
+
+ case W_META_RESTOREDC:
+ {
+ pOut->Pop();
+ }
+ break;
+
+ case W_META_SETPIXEL:
+ {
+ const Color aColor = ReadColor();
+ pOut->DrawPixel( ReadYX(), aColor );
+ }
+ break;
+
+ case W_META_OFFSETCLIPRGN:
+ {
+ pOut->MoveClipRegion( ReadYXExt() );
+ }
+ break;
+
+ case W_META_TEXTOUT:
+ {
+ sal_uInt16 nLength = 0;
+ *pWMF >> nLength;
+ if ( nLength )
+ {
+ char* pChar = new char[ ( nLength + 1 ) &~ 1 ];
+ pWMF->Read( pChar, ( nLength + 1 ) &~ 1 );
+ String aText( pChar, nLength, pOut->GetCharSet() );
+ delete[] pChar;
+ Point aPosition( ReadYX() );
+ pOut->DrawText( aPosition, aText );
+ }
+ }
+ break;
+
+ case W_META_EXTTEXTOUT:
+ {
+ sal_uInt16 nLen = 0, nOptions = 0;
+ sal_Int32 nRecordPos, nRecordSize = 0, nOriginalTextLen, nNewTextLen;
+ Point aPosition;
+ Rectangle aRect;
+ sal_Int32* pDXAry = NULL;
+
+ pWMF->SeekRel(-6);
+ nRecordPos = pWMF->Tell();
+ *pWMF >> nRecordSize;
+ pWMF->SeekRel(2);
+ aPosition = ReadYX();
+ *pWMF >> nLen >> nOptions;
+
+ sal_Int32 nTextLayoutMode = TEXT_LAYOUT_DEFAULT;
+ if ( nOptions & ETO_RTLREADING )
+ nTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
+ pOut->SetTextLayoutMode( nTextLayoutMode );
+ DBG_ASSERT( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in WMF" );
+
+ // Nur wenn der Text auch Zeichen enthaelt, macht die Ausgabe Sinn
+ if( nLen )
+ {
+ nOriginalTextLen = nLen;
+ if( nOptions & ETO_CLIPPED )
+ {
+ const Point aPt1( ReadPoint() );
+ const Point aPt2( ReadPoint() );
+ aRect = Rectangle( aPt1, aPt2 );
+ }
+ char* pChar = new char[ ( nOriginalTextLen + 1 ) &~ 1 ];
+ pWMF->Read( pChar, ( nOriginalTextLen + 1 ) &~ 1 );
+ String aText( pChar, (sal_uInt16)nOriginalTextLen, pOut->GetCharSet() );// after this conversion the text may contain
+ nNewTextLen = aText.Len(); // less character (japanese version), so the
+ delete[] pChar; // dxAry will not fit
+
+ if ( nNewTextLen )
+ {
+ sal_uInt32 nMaxStreamPos = nRecordPos + ( nRecordSize << 1 );
+ sal_Int32 nDxArySize = nMaxStreamPos - pWMF->Tell();
+ sal_Int32 nDxAryEntries = nDxArySize >> 1;
+ sal_Bool bUseDXAry = sal_False;
+
+ if ( ( ( nDxAryEntries % nOriginalTextLen ) == 0 ) && ( nNewTextLen <= nOriginalTextLen ) )
+ {
+ sal_Int16 nDx = 0, nDxTmp = 0;
+ sal_uInt16 i; //needed just outside the for
+ pDXAry = new sal_Int32[ nNewTextLen ];
+ for (i = 0; i < nNewTextLen; i++ )
+ {
+ if ( pWMF->Tell() >= nMaxStreamPos )
+ break;
+ *pWMF >> nDx;
+ if ( nNewTextLen != nOriginalTextLen )
+ {
+ sal_Unicode nUniChar = aText.GetChar(i);
+ rtl::OString aTmp(&nUniChar, 1, pOut->GetCharSet());
+ if ( aTmp.getLength() > 1 )
+ {
+ sal_Int32 nDxCount = aTmp.getLength() - 1;
+ if ( ( ( nDxCount * 2 ) + pWMF->Tell() ) > nMaxStreamPos )
+ break;
+ while ( nDxCount-- )
+ {
+ *pWMF >> nDxTmp;
+ nDx = nDx + nDxTmp;
+ }
+ }
+ }
+ pDXAry[ i ] = nDx;
+ }
+ if ( i == nNewTextLen )
+ bUseDXAry = sal_True;
+ }
+ if ( pDXAry && bUseDXAry )
+ pOut->DrawText( aPosition, aText, pDXAry );
+ else
+ pOut->DrawText( aPosition, aText );
+ }
+ }
+ delete[] pDXAry;
+
+ }
+ break;
+
+ case W_META_SELECTOBJECT:
+ {
+ sal_Int16 nObjIndex = 0;
+ *pWMF >> nObjIndex;
+ pOut->SelectObject( nObjIndex );
+ }
+ break;
+
+ case W_META_SETTEXTALIGN:
+ {
+ sal_uInt16 nAlign = 0;
+ *pWMF >> nAlign;
+ pOut->SetTextAlign( nAlign );
+ }
+ break;
+
+ case W_META_BITBLT:
+ {
+ // 0-3 : nWinROP #93454#
+ // 4-5 : y offset of source bitmap
+ // 6-7 : x offset of source bitmap
+ // 8-9 : used height of source bitmap
+ // 10-11 : used width of source bitmap
+ // 12-13 : destination position y (in pixel)
+ // 14-15 : destination position x (in pixel)
+ // 16-17 : dont know
+ // 18-19 : Width Bitmap in Pixel
+ // 20-21 : Height Bitmap in Pixel
+ // 22-23 : bytes per scanline
+ // 24 : planes
+ // 25 : bitcount
+
+ sal_Int32 nWinROP = 0;
+ sal_uInt16 nSx = 0, nSy = 0, nSxe = 0, nSye = 0, nDontKnow = 0, nWidth = 0, nHeight = 0, nBytesPerScan = 0;
+ sal_uInt8 nPlanes, nBitCount;
+
+ *pWMF >> nWinROP
+ >> nSy >> nSx >> nSye >> nSxe;
+ Point aPoint( ReadYX() );
+ *pWMF >> nDontKnow >> nWidth >> nHeight >> nBytesPerScan >> nPlanes >> nBitCount;
+
+ if ( nWidth && nHeight && ( nPlanes == 1 ) && ( nBitCount == 1 ) )
+ {
+ Bitmap aBmp( Size( nWidth, nHeight ), nBitCount );
+ BitmapWriteAccess* pAcc;
+ pAcc = aBmp.AcquireWriteAccess();
+ if ( pAcc )
+ {
+ for (sal_uInt16 y = 0; y < nHeight; y++ )
+ {
+ sal_uInt16 x = 0;
+ for (sal_uInt16 scan = 0; scan < nBytesPerScan; scan++ )
+ {
+ sal_Int8 nEightPixels = 0;
+ *pWMF >> nEightPixels;
+ for (sal_Int8 i = 7; i >= 0; i-- )
+ {
+ if ( x < nWidth )
+ {
+ pAcc->SetPixel( y, x, (nEightPixels>>i)&1 );
+ }
+ x++;
+ }
+ }
+ }
+ aBmp.ReleaseAccess( pAcc );
+ if ( nSye && nSxe &&
+ ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
+ ( ( nSy + nSye <= aBmp.GetSizePixel().Height() ) ) )
+ {
+ Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
+ aBmp.Crop( aCropRect );
+ }
+ Rectangle aDestRect( aPoint, Size( nSxe, nSye ) );
+ aBmpSaveList.push_back( new BSaveStruct( aBmp, aDestRect, nWinROP, pOut->GetFillStyle () ) );
+ }
+ }
+ }
+ break;
+
+ case W_META_STRETCHBLT:
+ case W_META_DIBBITBLT:
+ case W_META_DIBSTRETCHBLT:
+ case W_META_STRETCHDIB:
+ {
+ sal_Int32 nWinROP = 0;
+ sal_uInt16 nSx = 0, nSy = 0, nSxe = 0, nSye = 0, nUsage = 0;
+ Bitmap aBmp;
+
+ *pWMF >> nWinROP;
+
+ if( nFunc == W_META_STRETCHDIB )
+ *pWMF >> nUsage;
+
+ // nSye and nSxe is the number of pixels that has to been used
+ // If they are set to zero, it is as indicator not to scale the bitmap later
+ //
+ if( nFunc == W_META_STRETCHDIB || nFunc == W_META_STRETCHBLT || nFunc == W_META_DIBSTRETCHBLT )
+ *pWMF >> nSye >> nSxe;
+
+ // nSy and nx is the offset of the first pixel
+ *pWMF >> nSy >> nSx;
+
+ if( nFunc == W_META_STRETCHDIB || nFunc == W_META_DIBBITBLT || nFunc == W_META_DIBSTRETCHBLT )
+ {
+ if ( nWinROP == PATCOPY )
+ *pWMF >> nUsage; // i don't know anything of this parameter, so its called nUsage
+ // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), sal_False );
+
+ Size aDestSize( ReadYXExt() );
+ if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
+ {
+ Rectangle aDestRect( ReadYX(), aDestSize );
+ if ( nWinROP != PATCOPY )
+ aBmp.Read( *pWMF, sal_False );
+
+ // test if it is sensible to crop
+ if ( nSye && nSxe &&
+ ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
+ ( ( nSy + nSye <= aBmp.GetSizePixel().Height() ) ) )
+ {
+ Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
+ aBmp.Crop( aCropRect );
+ }
+ aBmpSaveList.push_back( new BSaveStruct( aBmp, aDestRect, nWinROP, pOut->GetFillStyle () ) );
+ }
+ }
+ }
+ break;
+
+ case W_META_DIBCREATEPATTERNBRUSH:
+ {
+ Bitmap aBmp;
+ BitmapReadAccess* pBmp;
+ sal_uInt32 nRed = 0, nGreen = 0, nBlue = 0, nCount = 1;
+ sal_uInt16 nFunction = 0;
+
+ *pWMF >> nFunction >> nFunction;
+
+ aBmp.Read( *pWMF, sal_False );
+ pBmp = aBmp.AcquireReadAccess();
+ if ( pBmp )
+ {
+ for ( sal_Int32 y = 0; y < pBmp->Height(); y++ )
+ {
+ for ( sal_Int32 x = 0; x < pBmp->Width(); x++ )
+ {
+ const BitmapColor aColor( pBmp->GetColor( y, x ) );
+
+ nRed += aColor.GetRed();
+ nGreen += aColor.GetGreen();
+ nBlue += aColor.GetBlue();
+ }
+ }
+ nCount = pBmp->Height() * pBmp->Width();
+ if ( !nCount )
+ nCount++;
+ aBmp.ReleaseAccess( pBmp );
+ }
+ Color aColor( (sal_uInt8)( nRed / nCount ), (sal_uInt8)( nGreen / nCount ), (sal_uInt8)( nBlue / nCount ) );
+ pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( aColor, sal_False ) );
+ }
+ break;
+
+ case W_META_DELETEOBJECT:
+ {
+ sal_Int16 nIndex = 0;
+ *pWMF >> nIndex;
+ pOut->DeleteObject( nIndex );
+ }
+ break;
+
+ case W_META_CREATEPALETTE:
+ {
+ pOut->CreateObject( GDI_DUMMY );
+ }
+ break;
+
+ case W_META_CREATEBRUSH:
+ {
+ pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ), sal_False ) );
+ }
+ break;
+
+ case W_META_CREATEPATTERNBRUSH:
+ {
+ pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ), sal_False ) );
+ }
+ break;
+
+ case W_META_CREATEPENINDIRECT:
+ {
+ LineInfo aLineInfo;
+ sal_uInt16 nStyle = 0, nWidth = 0, nHeight = 0;
+
+ *pWMF >> nStyle >> nWidth >> nHeight;
+
+ if ( nWidth )
+ aLineInfo.SetWidth( nWidth );
+
+ sal_Bool bTransparent = sal_False;
+ sal_uInt16 nDashCount = 0;
+ sal_uInt16 nDotCount = 0;
+ switch( nStyle )
+ {
+ case PS_DASHDOTDOT :
+ nDotCount++;
+ case PS_DASHDOT :
+ nDashCount++;
+ case PS_DOT :
+ nDotCount++;
+ break;
+ case PS_DASH :
+ nDashCount++;
+ break;
+ case PS_NULL :
+ bTransparent = sal_True;
+ aLineInfo.SetStyle( LINE_NONE );
+ break;
+ default :
+ case PS_INSIDEFRAME :
+ case PS_SOLID :
+ aLineInfo.SetStyle( LINE_SOLID );
+ }
+ if ( nDashCount | nDotCount )
+ {
+ aLineInfo.SetStyle( LINE_DASH );
+ aLineInfo.SetDashCount( nDashCount );
+ aLineInfo.SetDotCount( nDotCount );
+ }
+ pOut->CreateObject( GDI_PEN, new WinMtfLineStyle( ReadColor(), aLineInfo, bTransparent ) );
+ }
+ break;
+
+ case W_META_CREATEBRUSHINDIRECT:
+ {
+ sal_uInt16 nStyle = 0;
+ *pWMF >> nStyle;
+ pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( ReadColor(), ( nStyle == BS_HOLLOW ) ? sal_True : sal_False ) );
+ }
+ break;
+
+ case W_META_CREATEFONTINDIRECT:
+ {
+ Size aFontSize;
+ char lfFaceName[ LF_FACESIZE ];
+ sal_Int16 lfEscapement = 0, lfOrientation = 0, lfWeight = 0; // ( formerly sal_uInt16 )
+
+ LOGFONTW aLogFont;
+ aFontSize = ReadYXExt();
+ *pWMF >> lfEscapement >> lfOrientation >> lfWeight
+ >> aLogFont.lfItalic >> aLogFont.lfUnderline >> aLogFont.lfStrikeOut >> aLogFont.lfCharSet >> aLogFont.lfOutPrecision
+ >> aLogFont.lfClipPrecision >> aLogFont.lfQuality >> aLogFont.lfPitchAndFamily;
+ pWMF->Read( lfFaceName, LF_FACESIZE );
+ aLogFont.lfWidth = aFontSize.Width();
+ aLogFont.lfHeight = aFontSize.Height();
+ aLogFont.lfEscapement = lfEscapement;
+ aLogFont.lfOrientation = lfOrientation;
+ aLogFont.lfWeight = lfWeight;
+
+ CharSet eCharSet;
+ if ( ( aLogFont.lfCharSet == OEM_CHARSET ) || ( aLogFont.lfCharSet == DEFAULT_CHARSET ) )
+ eCharSet = osl_getThreadTextEncoding();
+ else
+ eCharSet = rtl_getTextEncodingFromWindowsCharset( aLogFont.lfCharSet );
+ if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
+ eCharSet = osl_getThreadTextEncoding();
+ if ( eCharSet == RTL_TEXTENCODING_SYMBOL )
+ eCharSet = RTL_TEXTENCODING_MS_1252;
+ aLogFont.alfFaceName = UniString( lfFaceName, eCharSet );
+
+ pOut->CreateObject( GDI_FONT, new WinMtfFontStyle( aLogFont ) );
+ }
+ break;
+
+ case W_META_CREATEBITMAPINDIRECT:
+ {
+ pOut->CreateObject( GDI_DUMMY );
+ }
+ break;
+
+ case W_META_CREATEBITMAP:
+ {
+ pOut->CreateObject( GDI_DUMMY );
+ }
+ break;
+
+ case W_META_CREATEREGION:
+ {
+ pOut->CreateObject( GDI_DUMMY );
+ }
+ break;
+
+ case W_META_EXCLUDECLIPRECT :
+ {
+ pOut->ExcludeClipRect( ReadRectangle() );
+ }
+ break;
+
+ case W_META_PATBLT:
+ {
+ sal_uInt32 nROP = 0, nOldROP = 0;
+ *pWMF >> nROP;
+ Size aSize = ReadYXExt();
+ nOldROP = pOut->SetRasterOp( nROP );
+ pOut->DrawRect( Rectangle( ReadYX(), aSize ), sal_False );
+ pOut->SetRasterOp( nOldROP );
+ }
+ break;
+
+ case W_META_SELECTCLIPREGION:
+ {
+ sal_Int16 nObjIndex = 0;
+ *pWMF >> nObjIndex;
+ if ( !nObjIndex )
+ {
+ PolyPolygon aEmptyPolyPoly;
+ pOut->SetClipPath( aEmptyPolyPoly, RGN_COPY, sal_True );
+ }
+ }
+ break;
+
+ case W_META_ESCAPE :
+ {
+ // nRecSize has been checked previously to be greater than 3
+ sal_uInt64 nMetaRecSize = static_cast< sal_uInt64 >( nRecSize - 2 ) * 2;
+ sal_uInt64 nMetaRecEndPos = pWMF->Tell() + nMetaRecSize;
+
+ // taking care that nRecSize does not exceed the maximal stream position
+ if ( nMetaRecEndPos > nEndPos )
+ {
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ break;
+ }
+ if ( nRecSize >= 4 ) // minimal escape lenght
+ {
+ sal_uInt16 nMode = 0, nLen = 0;
+ *pWMF >> nMode
+ >> nLen;
+ if ( ( nMode == W_MFCOMMENT ) && ( nLen >= 4 ) )
+ {
+ sal_uInt32 nNewMagic = 0; // we have to read int32 for
+ *pWMF >> nNewMagic; // META_ESCAPE_ENHANCED_METAFILE CommentIdentifier
+
+ if( nNewMagic == 0x2c2a4f4f && nLen >= 14 )
+ {
+ sal_uInt16 nMagic2 = 0;
+ *pWMF >> nMagic2;
+ if( nMagic2 == 0x0a ) // 2nd half of magic
+ { // continue with private escape
+ sal_uInt32 nCheck = 0, nEsc = 0;
+ *pWMF >> nCheck
+ >> nEsc;
+
+ sal_uInt32 nEscLen = nLen - 14;
+ if ( nEscLen <= ( nRecSize * 2 ) )
+ {
+#ifdef OSL_BIGENDIAN
+ sal_uInt32 nTmp = OSL_SWAPDWORD( nEsc );
+ sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
+#else
+ sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
+#endif
+ sal_Int8* pData = NULL;
+
+ if ( ( static_cast< sal_uInt64 >( nEscLen ) + pWMF->Tell() ) > nMetaRecEndPos )
+ {
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ break;
+ }
+ if ( nEscLen > 0 )
+ {
+ pData = new sal_Int8[ nEscLen ];
+ pWMF->Read( pData, nEscLen );
+ nCheckSum = rtl_crc32( nCheckSum, pData, nEscLen );
+ }
+ if ( nCheck == nCheckSum )
+ {
+ switch( nEsc )
+ {
+ case PRIVATE_ESCAPE_UNICODE :
+ { // we will use text instead of polygons only if we have the correct font
+ if ( aVDev.IsFontAvailable( pOut->GetFont().GetName() ) )
+ {
+ Point aPt;
+ String aString;
+ sal_uInt32 nStringLen, nDXCount;
+ sal_Int32* pDXAry = NULL;
+ SvMemoryStream aMemoryStream( nEscLen );
+ aMemoryStream.Write( pData, nEscLen );
+ aMemoryStream.Seek( STREAM_SEEK_TO_BEGIN );
+ //#fdo39428 SvStream no longer supports operator>>(long&)
+ sal_Int32 nTmpX(0), nTmpY(0);
+ aMemoryStream >> nTmpX
+ >> nTmpY
+ >> nStringLen;
+ aPt.X() = nTmpX;
+ aPt.Y() = nTmpY;
+
+ if ( ( static_cast< sal_uInt64 >( nStringLen ) * sizeof( sal_Unicode ) ) < ( nEscLen - aMemoryStream.Tell() ) )
+ {
+
+ aString = read_uInt16s_ToOUString(aMemoryStream, nStringLen);
+ aMemoryStream >> nDXCount;
+ if ( ( static_cast< sal_uInt64 >( nDXCount ) * sizeof( sal_Int32 ) ) >= ( nEscLen - aMemoryStream.Tell() ) )
+ nDXCount = 0;
+ if ( nDXCount )
+ pDXAry = new sal_Int32[ nDXCount ];
+ for (sal_uInt32 i = 0; i < nDXCount; i++ )
+ aMemoryStream >> pDXAry[ i ];
+ aMemoryStream >> nSkipActions;
+ pOut->DrawText( aPt, aString, pDXAry );
+ delete[] pDXAry;
+ }
+ }
+ }
+ break;
+ }
+ }
+ delete[] pData;
+ }
+ }
+ }
+ else if ( (nNewMagic == static_cast< sal_uInt32 >(0x43464D57)) && (nLen >= 34) && ( (sal_Int32)(nLen + 10) <= (sal_Int32)(nRecSize * 2) ))
+ {
+ sal_uInt32 nComType = 0, nVersion = 0, nFlags = 0, nComRecCount = 0,
+ nCurRecSize = 0, nRemainingSize = 0, nEMFTotalSize = 0;
+ sal_uInt16 nCheck = 0;
+
+ *pWMF >> nComType >> nVersion >> nCheck >> nFlags
+ >> nComRecCount >> nCurRecSize
+ >> nRemainingSize >> nEMFTotalSize; // the nRemainingSize is not mentioned in MSDN documentation
+ // but it seems to be required to read in data produced by OLE
+
+ if( nComType == 0x01 && nVersion == 0x10000 && nComRecCount )
+ {
+ if( !nEMFRec )
+ { // first EMF comment
+ nEMFRecCount = nComRecCount;
+ nEMFSize = nEMFTotalSize;
+ pEMFStream = new SvMemoryStream( nEMFSize );
+ }
+ else if( ( nEMFRecCount != nComRecCount ) || ( nEMFSize != nEMFTotalSize ) ) // add additional checks here
+ {
+ // total records should be the same as in previous comments
+ nEMFRecCount = 0xFFFFFFFF;
+ delete pEMFStream;
+ pEMFStream = NULL;
+ }
+ nEMFRec++;
+
+ if( pEMFStream && nCurRecSize + 34 > nLen )
+ {
+ nEMFRecCount = 0xFFFFFFFF;
+ delete pEMFStream;
+ pEMFStream = NULL;
+ }
+
+ if( pEMFStream )
+ {
+ sal_Int8* pBuf = new sal_Int8[ nCurRecSize ];
+ sal_uInt32 nCount = pWMF->Read( pBuf, nCurRecSize );
+ if( nCount == nCurRecSize )
+ pEMFStream->Write( pBuf, nCount );
+ delete[] pBuf;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case W_META_SETRELABS:
+ case W_META_SETPOLYFILLMODE:
+ case W_META_SETSTRETCHBLTMODE:
+ case W_META_SETTEXTCHAREXTRA:
+ case W_META_SETTEXTJUSTIFICATION:
+ case W_META_FLOODFILL :
+ case W_META_FILLREGION:
+ case W_META_FRAMEREGION:
+ case W_META_INVERTREGION:
+ case W_META_PAINTREGION:
+ case W_META_DRAWTEXT:
+ case W_META_SETMAPPERFLAGS:
+ case W_META_SETDIBTODEV:
+ case W_META_SELECTPALETTE:
+ case W_META_REALIZEPALETTE:
+ case W_META_ANIMATEPALETTE:
+ case W_META_SETPALENTRIES:
+ case W_META_RESIZEPALETTE:
+ case W_META_EXTFLOODFILL:
+ case W_META_RESETDC:
+ case W_META_STARTDOC:
+ case W_META_STARTPAGE:
+ case W_META_ENDPAGE:
+ case W_META_ABORTDOC:
+ case W_META_ENDDOC:
+ break;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool WMFReader::ReadHeader()
+{
+ sal_Size nStrmPos = pWMF->Tell();
+
+ sal_uInt32 nPlaceableMetaKey(0);
+ // Einlesen des METAFILEHEADER, falls vorhanden
+ *pWMF >> nPlaceableMetaKey;
+ if (!pWMF->good())
+ return false;
+
+ Rectangle aPlaceableBound;
+
+ if (nPlaceableMetaKey == 0x9ac6cdd7L)
+ { //TODO do some real error handling here
+ sal_Int16 nVal;
+
+ // Skip reserved bytes
+ pWMF->SeekRel(2);
+
+ // BoundRect
+ *pWMF >> nVal;
+ aPlaceableBound.Left() = nVal;
+ *pWMF >> nVal;
+ aPlaceableBound.Top() = nVal;
+ *pWMF >> nVal;
+ aPlaceableBound.Right() = nVal;
+ *pWMF >> nVal;
+ aPlaceableBound.Bottom() = nVal;
+
+ // inch
+ *pWMF >> nUnitsPerInch;
+
+ // reserved
+ pWMF->SeekRel( 4 );
+
+ // Skip and don't check the checksum
+ pWMF->SeekRel( 2 );
+ }
+ else
+ {
+ nUnitsPerInch = 96;
+ pWMF->Seek( nStrmPos + 18 ); // set the streampos to the start of the the metaactions
+ GetPlaceableBound( aPlaceableBound, pWMF );
+ pWMF->Seek( nStrmPos );
+ if ( pExternalHeader != NULL && ( pExternalHeader->mapMode == MM_ISOTROPIC
+ || pExternalHeader->mapMode == MM_ANISOTROPIC ) )
+ {
+ // #n417818#: If we have an external header then overwrite the bounds!
+ Rectangle aExtRect(0, 0,
+ pExternalHeader->xExt*567*nUnitsPerInch/1440/1000,
+ pExternalHeader->yExt*567*nUnitsPerInch/1440/1000);
+ GetWinExtMax( aExtRect, aPlaceableBound, pExternalHeader->mapMode );
+ pOut->SetMapMode( pExternalHeader->mapMode );
+ }
+ }
+
+ pOut->SetUnitsPerInch( nUnitsPerInch );
+ pOut->SetWinOrg( aPlaceableBound.TopLeft() );
+ Size aWMFSize( labs( aPlaceableBound.GetWidth() ), labs( aPlaceableBound.GetHeight() ) );
+ pOut->SetWinExt( aWMFSize );
+
+ Size aDevExt( 10000, 10000 );
+ if( ( labs( aWMFSize.Width() ) > 1 ) && ( labs( aWMFSize.Height() ) > 1 ) )
+ {
+ const Fraction aFrac( 1, nUnitsPerInch );
+ MapMode aWMFMap( MAP_INCH, Point(), aFrac, aFrac );
+ Size aSize100( OutputDevice::LogicToLogic( aWMFSize, aWMFMap, MAP_100TH_MM ) );
+ aDevExt = Size( labs( aSize100.Width() ), labs( aSize100.Height() ) );
+ }
+ pOut->SetDevExt( aDevExt );
+
+ // Einlesen des METAHEADER
+ sal_uInt32 nMetaKey(0);
+ *pWMF >> nMetaKey; // Typ und Headergroesse
+ if (!pWMF->good())
+ return false;
+ if (nMetaKey != 0x00090001)
+ {
+ sal_uInt16 aNextWord(0);
+ *pWMF >> aNextWord;
+ if (nMetaKey != 0x10000 || aNextWord != 0x09)
+ {
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ return false;
+ }
+ }
+
+ pWMF->SeekRel( 2 ); // Version (von Windows)
+ pWMF->SeekRel( 4 ); // Size (der Datei in Words)
+ pWMF->SeekRel( 2 ); // NoObjects (Maximale Anzahl der gleichzeitigen Objekte)
+ pWMF->SeekRel( 4 ); // MaxRecord (Groesse des groessten Records in Words)
+ pWMF->SeekRel( 2 ); // NoParameters (Unused
+
+ return pWMF->good();
+}
+
+void WMFReader::ReadWMF()
+{
+ sal_uInt16 nFunction;
+ sal_uLong nPos, nPercent, nLastPercent;
+
+ nSkipActions = 0;
+ nCurrentAction = 0;
+ nUnicodeEscapeAction = 0;
+
+ pEMFStream = NULL;
+ nEMFRecCount = 0;
+ nEMFRec = 0;
+ nEMFSize = 0;
+
+ sal_Bool bEMFAvailable = sal_False;
+
+ pOut->SetMapMode( MM_ANISOTROPIC );
+ pOut->SetWinOrg( Point() );
+ pOut->SetWinExt( Size( 1, 1 ) );
+ pOut->SetDevExt( Size( 10000, 10000 ) );
+
+ nEndPos=pWMF->Seek( STREAM_SEEK_TO_END );
+ pWMF->Seek( nStartPos );
+ Callback( (sal_uInt16) ( nLastPercent = 0 ) );
+
+ if ( ReadHeader( ) )
+ {
+
+ nPos = pWMF->Tell();
+
+ if( nEndPos - nStartPos )
+ {
+ while( sal_True )
+ {
+ nCurrentAction++;
+ nPercent = ( nPos - nStartPos ) * 100 / ( nEndPos - nStartPos );
+
+ if( nLastPercent + 4 <= nPercent )
+ {
+ Callback( (sal_uInt16) nPercent );
+ nLastPercent = nPercent;
+ }
+ *pWMF >> nRecSize >> nFunction;
+
+ if( pWMF->GetError()
+ || ( nRecSize < 3 )
+ || ( nRecSize == 3
+ && nFunction == 0
+ )
+ || pWMF->IsEof()
+ )
+ {
+ if( pWMF->IsEof() )
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+
+ break;
+ }
+ if ( !bEMFAvailable )
+ {
+ if( !aBmpSaveList.empty()
+ && ( nFunction != W_META_STRETCHDIB )
+ && ( nFunction != W_META_DIBBITBLT )
+ && ( nFunction != W_META_DIBSTRETCHBLT )
+ )
+ {
+ pOut->ResolveBitmapActions( aBmpSaveList );
+ }
+
+ if ( !nSkipActions )
+ ReadRecordParams( nFunction );
+ else
+ nSkipActions--;
+
+ if( pEMFStream && nEMFRecCount == nEMFRec )
+ {
+ GDIMetaFile aMeta;
+ pEMFStream->Seek( 0 );
+ EnhWMFReader* pEMFReader = new EnhWMFReader ( *pEMFStream, aMeta );
+ bEMFAvailable = pEMFReader->ReadEnhWMF();
+ delete pEMFReader; // destroy first!!!
+
+ if( bEMFAvailable )
+ {
+ pOut->AddFromGDIMetaFile( aMeta );
+ pOut->SetrclFrame( Rectangle( Point(0, 0), aMeta.GetPrefSize()));
+
+ // the stream needs to be set to the wmf end position,
+ // otherwise the GfxLink that is created will be incorrect
+ // (leading to graphic loss after swapout/swapin).
+ // so we will proceed normally, but are ignoring further wmf
+ // records
+ }
+ else
+ {
+ // something went wrong
+ // continue with WMF, don't try this again
+ delete pEMFStream;
+ pEMFStream = NULL;
+ }
+ }
+ }
+ nPos += nRecSize * 2;
+ if ( nPos <= nEndPos )
+ pWMF->Seek( nPos );
+ else
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ }
+ }
+ else
+ pWMF->SetError( SVSTREAM_GENERALERROR );
+
+ if( !pWMF->GetError() && !aBmpSaveList.empty() )
+ pOut->ResolveBitmapActions( aBmpSaveList );
+ }
+ if ( pWMF->GetError() )
+ pWMF->Seek( nStartPos );
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool WMFReader::GetPlaceableBound( Rectangle& rPlaceableBound, SvStream* pStm )
+{
+ sal_Bool bRet = sal_True;
+
+ rPlaceableBound.Left() = (sal_Int32)0x7fffffff;
+ rPlaceableBound.Top() = (sal_Int32)0x7fffffff;
+ rPlaceableBound.Right() = (sal_Int32)0x80000000;
+ rPlaceableBound.Bottom() = (sal_Int32)0x80000000;
+
+ sal_uInt32 nPos = pStm->Tell();
+ sal_uInt32 nEnd = pStm->Seek( STREAM_SEEK_TO_END );
+
+ pStm->Seek( nPos );
+
+ if( nEnd - nPos )
+ {
+ sal_Int16 nMapMode = MM_ANISOTROPIC;
+ sal_uInt16 nFunction;
+ sal_uInt32 nRSize;
+
+ while( bRet )
+ {
+ *pStm >> nRSize >> nFunction;
+
+ if( pStm->GetError() || ( nRSize < 3 ) || ( nRSize==3 && nFunction==0 ) || pStm->IsEof() )
+ {
+ if( pStm->IsEof() )
+ {
+ pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ bRet = sal_False;
+ }
+ break;
+ }
+ switch( nFunction )
+ {
+ case W_META_SETWINDOWORG:
+ {
+ Point aWinOrg;
+ aWinOrg = ReadYX();
+ rPlaceableBound.SetPos( aWinOrg );
+ }
+ break;
+
+ case W_META_SETWINDOWEXT:
+ {
+ sal_Int16 nWidth(0), nHeight(0);
+ *pStm >> nHeight >> nWidth;
+ rPlaceableBound.SetSize( Size( nWidth, nHeight ) );
+ }
+ break;
+
+ case W_META_SETMAPMODE :
+ *pStm >> nMapMode;
+ break;
+
+ case W_META_MOVETO:
+ case W_META_LINETO:
+ GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
+ break;
+
+ case W_META_RECTANGLE:
+ case W_META_INTERSECTCLIPRECT:
+ case W_META_EXCLUDECLIPRECT :
+ case W_META_ELLIPSE:
+ GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
+ break;
+
+ case W_META_ROUNDRECT:
+ ReadYXExt(); // size
+ GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
+ break;
+
+ case W_META_ARC:
+ case W_META_PIE:
+ case W_META_CHORD:
+ ReadYX(); // end
+ ReadYX(); // start
+ GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
+ break;
+
+ case W_META_POLYGON:
+ {
+ sal_uInt16 nPoints;
+ *pStm >> nPoints;
+ for(sal_uInt16 i = 0; i < nPoints; i++ )
+ GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
+ }
+ break;
+
+ case W_META_POLYPOLYGON:
+ {
+ bool bRecordOk = true;
+ sal_uInt16 nPoly, nPoints = 0;
+ *pStm >> nPoly;
+ for(sal_uInt16 i = 0; i < nPoly; i++ )
+ {
+ sal_uInt16 nP = 0;
+ *pStm >> nP;
+ if (nP > SAL_MAX_UINT16 - nPoints)
+ {
+ bRecordOk = false;
+ break;
+ }
+ nPoints += nP;
+ }
+
+ SAL_WARN_IF(!bRecordOk, "svtools.filter", "polypolygon record has more polygons than we can handle");
+
+ bRecordOk &= pStm->good();
+
+ if (!bRecordOk)
+ {
+ pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ bRet = sal_False;
+ break;
+ }
+
+ for (sal_uInt16 i = 0; i < nPoints; i++ )
+ GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
+
+ bRecordOk &= pStm->good();
+
+ if (!bRecordOk)
+ {
+ pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ bRet = sal_False;
+ break;
+ }
+ }
+ break;
+
+ case W_META_POLYLINE:
+ {
+ sal_uInt16 nPoints;
+ *pStm >> nPoints;
+ for(sal_uInt16 i = 0; i < nPoints; i++ )
+ GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
+ }
+ break;
+
+ case W_META_SETPIXEL:
+ {
+ ReadColor();
+ GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
+ }
+ break;
+
+ case W_META_TEXTOUT:
+ {
+ sal_uInt16 nLength;
+ *pStm >> nLength;
+ // todo: we also have to take care of the text width
+ if ( nLength )
+ {
+ pStm->SeekRel( ( nLength + 1 ) &~ 1 );
+ GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
+ }
+ }
+ break;
+
+ case W_META_EXTTEXTOUT:
+ {
+ sal_uInt16 nLen, nOptions;
+ Point aPosition;
+
+ aPosition = ReadYX();
+ *pStm >> nLen >> nOptions;
+ // todo: we also have to take care of the text width
+ if( nLen )
+ GetWinExtMax( aPosition, rPlaceableBound, nMapMode );
+ }
+ break;
+ case W_META_BITBLT:
+ case W_META_STRETCHBLT:
+ case W_META_DIBBITBLT:
+ case W_META_DIBSTRETCHBLT:
+ case W_META_STRETCHDIB:
+ {
+ sal_Int32 nWinROP;
+ sal_uInt16 nSx, nSy, nSxe, nSye, nUsage;
+ *pStm >> nWinROP;
+
+ if( nFunction == W_META_STRETCHDIB )
+ *pStm >> nUsage;
+
+ // nSye and nSxe is the number of pixels that has to been used
+ if( nFunction == W_META_STRETCHDIB || nFunction == W_META_STRETCHBLT || nFunction == W_META_DIBSTRETCHBLT )
+ *pStm >> nSye >> nSxe;
+ else
+ nSye = nSxe = 0; // set this to zero as indicator not to scale the bitmap later
+
+ // nSy and nx is the offset of the first pixel
+ *pStm >> nSy >> nSx;
+
+ if( nFunction == W_META_STRETCHDIB || nFunction == W_META_DIBBITBLT || nFunction == W_META_DIBSTRETCHBLT )
+ {
+ if ( nWinROP == PATCOPY )
+ *pStm >> nUsage; // i don't know anything of this parameter, so its called nUsage
+ // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), sal_False );
+
+ Size aDestSize( ReadYXExt() );
+ if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
+ {
+ Rectangle aDestRect( ReadYX(), aDestSize );
+ GetWinExtMax( aDestRect, rPlaceableBound, nMapMode );
+ }
+ }
+ }
+ break;
+
+ case W_META_PATBLT:
+ {
+ sal_uInt32 nROP;
+ *pStm >> nROP;
+ Size aSize = ReadYXExt();
+ GetWinExtMax( Rectangle( ReadYX(), aSize ), rPlaceableBound, nMapMode );
+ }
+ break;
+ }
+ nPos += nRSize * 2;
+ if ( nPos <= nEnd )
+ pStm->Seek( nPos );
+ else
+ {
+ pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ bRet = sal_False;
+ }
+
+ }
+ }
+ else
+ {
+ pStm->SetError( SVSTREAM_GENERALERROR );
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+WMFReader::~WMFReader()
+{
+ if( pEMFStream )
+ delete pEMFStream;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/wmf.cxx b/vcl/source/filter/wmf/wmf.cxx
new file mode 100644
index 000000000000..9c3b7e6dc0e7
--- /dev/null
+++ b/vcl/source/filter/wmf/wmf.cxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include "winmtf.hxx"
+#include "emfwr.hxx"
+#include "wmfwr.hxx"
+#include <svtools/wmf.hxx>
+#include <comphelper/scopeguard.hxx>
+
+// -----------------------------------------------------------------------------
+
+sal_Bool ConvertWMFToGDIMetaFile( SvStream & rStreamWMF, GDIMetaFile & rGDIMetaFile, FilterConfigItem* pConfigItem, WMF_EXTERNALHEADER *pExtHeader )
+{
+ sal_uInt32 nMetaType;
+ sal_uInt32 nOrgPos = rStreamWMF.Tell();
+ sal_uInt16 nOrigNumberFormat = rStreamWMF.GetNumberFormatInt();
+ rStreamWMF.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rStreamWMF.Seek( 0x28 );
+ rStreamWMF >> nMetaType;
+ rStreamWMF.Seek( nOrgPos );
+ if ( nMetaType == 0x464d4520 )
+ {
+ if ( EnhWMFReader( rStreamWMF, rGDIMetaFile, pConfigItem ).ReadEnhWMF() == sal_False )
+ rStreamWMF.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ }
+ else
+ {
+ WMFReader( rStreamWMF, rGDIMetaFile, pConfigItem, pExtHeader ).ReadWMF( );
+ }
+ rStreamWMF.SetNumberFormatInt( nOrigNumberFormat );
+ return !rStreamWMF.GetError();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool ReadWindowMetafile( SvStream& rStream, GDIMetaFile& rMTF, FilterConfigItem* pFilterConfigItem )
+{
+ sal_uInt32 nMetaType(0);
+ sal_uInt32 nOrgPos = rStream.Tell();
+
+ sal_uInt16 nOrigNumberFormat = rStream.GetNumberFormatInt();
+ rStream.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ //exception-safe reset nOrigNumberFormat at end of scope
+ const ::comphelper::ScopeGuard aScopeGuard(
+ boost::bind(&SvStream::SetNumberFormatInt, ::boost::ref(rStream),
+ nOrigNumberFormat));
+
+ rStream.Seek( 0x28 );
+ rStream >> nMetaType;
+ rStream.Seek( nOrgPos );
+
+ if (!rStream.good())
+ return false;
+
+ if ( nMetaType == 0x464d4520 )
+ {
+ if ( EnhWMFReader( rStream, rMTF, NULL ).ReadEnhWMF() == sal_False )
+ rStream.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ }
+ else
+ {
+ WMFReader( rStream, rMTF, pFilterConfigItem ).ReadWMF();
+ }
+
+ return rStream.good();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool ConvertGDIMetaFileToWMF( const GDIMetaFile & rMTF, SvStream & rTargetStream,
+ FilterConfigItem* pConfigItem, sal_Bool bPlaceable)
+{
+ WMFWriter aWMFWriter;
+ return aWMFWriter.WriteWMF( rMTF, rTargetStream, pConfigItem, bPlaceable );
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool ConvertGDIMetaFileToEMF( const GDIMetaFile & rMTF, SvStream & rTargetStream,
+ FilterConfigItem* pConfigItem )
+{
+ EMFWriter aEMFWriter(rTargetStream);
+ return aEMFWriter.WriteEMF( rMTF, pConfigItem );
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool WriteWindowMetafileBits( SvStream& rStream, const GDIMetaFile& rMTF )
+{
+ return WMFWriter().WriteWMF( rMTF, rStream, NULL, sal_False );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/wmfwr.cxx b/vcl/source/filter/wmf/wmfwr.cxx
new file mode 100644
index 000000000000..c9baef6b36f5
--- /dev/null
+++ b/vcl/source/filter/wmf/wmfwr.cxx
@@ -0,0 +1,2052 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include "wmfwr.hxx"
+#include <unotools/fontcvt.hxx>
+#include "emfwr.hxx"
+#include <rtl/crc.h>
+#include <rtl/tencinfo.h>
+#include <tools/bigint.hxx>
+#include <tools/helpers.hxx>
+#include <tools/tenccvt.hxx>
+#include <osl/endian.h>
+#include <i18nutil/unicode.hxx> //unicode::getUnicodeScriptType
+
+#include <vcl/metric.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+//====================== MS-Windows-defines ===============================
+
+#define W_META_SETBKCOLOR 0x0201
+#define W_META_SETBKMODE 0x0102
+#define W_META_SETMAPMODE 0x0103
+#define W_META_SETROP2 0x0104
+#define W_META_SETRELABS 0x0105
+#define W_META_SETPOLYFILLMODE 0x0106
+#define W_META_SETSTRETCHBLTMODE 0x0107
+#define W_META_SETTEXTCHAREXTRA 0x0108
+#define W_META_SETTEXTCOLOR 0x0209
+#define W_META_SETTEXTJUSTIFICATION 0x020A
+#define W_META_SETWINDOWORG 0x020B
+#define W_META_SETWINDOWEXT 0x020C
+#define W_META_SETVIEWPORTORG 0x020D
+#define W_META_SETVIEWPORTEXT 0x020E
+#define W_META_OFFSETWINDOWORG 0x020F
+#define W_META_SCALEWINDOWEXT 0x0410
+#define W_META_OFFSETVIEWPORTORG 0x0211
+#define W_META_SCALEVIEWPORTEXT 0x0412
+#define W_META_LINETO 0x0213
+#define W_META_MOVETO 0x0214
+#define W_META_EXCLUDECLIPRECT 0x0415
+#define W_META_INTERSECTCLIPRECT 0x0416
+#define W_META_ARC 0x0817
+#define W_META_ELLIPSE 0x0418
+#define W_META_FLOODFILL 0x0419
+#define W_META_PIE 0x081A
+#define W_META_RECTANGLE 0x041B
+#define W_META_ROUNDRECT 0x061C
+#define W_META_PATBLT 0x061D
+#define W_META_SAVEDC 0x001E
+#define W_META_SETPIXEL 0x041F
+#define W_META_OFFSETCLIPRGN 0x0220
+#define W_META_TEXTOUT 0x0521
+#define W_META_BITBLT 0x0922
+#define W_META_STRETCHBLT 0x0B23
+#define W_META_POLYGON 0x0324
+#define W_META_POLYLINE 0x0325
+#define W_META_ESCAPE 0x0626
+#define W_META_RESTOREDC 0x0127
+#define W_META_FILLREGION 0x0228
+#define W_META_FRAMEREGION 0x0429
+#define W_META_INVERTREGION 0x012A
+#define W_META_PAINTREGION 0x012B
+#define W_META_SELECTCLIPREGION 0x012C
+#define W_META_SELECTOBJECT 0x012D
+#define W_META_SETTEXTALIGN 0x012E
+#define W_META_DRAWTEXT 0x062F
+#define W_META_CHORD 0x0830
+#define W_META_SETMAPPERFLAGS 0x0231
+#define W_META_EXTTEXTOUT 0x0a32
+#define W_META_SETDIBTODEV 0x0d33
+#define W_META_SELECTPALETTE 0x0234
+#define W_META_REALIZEPALETTE 0x0035
+#define W_META_ANIMATEPALETTE 0x0436
+#define W_META_SETPALENTRIES 0x0037
+#define W_META_POLYPOLYGON 0x0538
+#define W_META_RESIZEPALETTE 0x0139
+#define W_META_DIBBITBLT 0x0940
+#define W_META_DIBSTRETCHBLT 0x0b41
+#define W_META_DIBCREATEPATTERNBRUSH 0x0142
+#define W_META_STRETCHDIB 0x0f43
+#define W_META_EXTFLOODFILL 0x0548
+#define W_META_RESETDC 0x014C
+#define W_META_STARTDOC 0x014D
+#define W_META_STARTPAGE 0x004F
+#define W_META_ENDPAGE 0x0050
+#define W_META_ABORTDOC 0x0052
+#define W_META_ENDDOC 0x005E
+#define W_META_DELETEOBJECT 0x01f0
+#define W_META_CREATEPALETTE 0x00f7
+#define W_META_CREATEBRUSH 0x00F8
+#define W_META_CREATEPATTERNBRUSH 0x01F9
+#define W_META_CREATEPENINDIRECT 0x02FA
+#define W_META_CREATEFONTINDIRECT 0x02FB
+#define W_META_CREATEBRUSHINDIRECT 0x02FC
+#define W_META_CREATEBITMAPINDIRECT 0x02FD
+#define W_META_CREATEBITMAP 0x06FE
+#define W_META_CREATEREGION 0x06FF
+
+#define W_TRANSPARENT 1
+#define W_OPAQUE 2
+
+#define W_R2_BLACK 1
+#define W_R2_NOTMERGEPEN 2
+#define W_R2_MASKNOTPEN 3
+#define W_R2_NOTCOPYPEN 4
+#define W_R2_MASKPENNOT 5
+#define W_R2_NOT 6
+#define W_R2_XORPEN 7
+#define W_R2_NOTMASKPEN 8
+#define W_R2_MASKPEN 9
+#define W_R2_NOTXORPEN 10
+#define W_R2_NOP 11
+#define W_R2_MERGENOTPEN 12
+#define W_R2_COPYPEN 13
+#define W_R2_MERGEPENNOT 14
+#define W_R2_MERGEPEN 15
+#define W_R2_WHITE 16
+
+#define W_TA_NOUPDATECP 0x0000
+#define W_TA_UPDATECP 0x0001
+#define W_TA_LEFT 0x0000
+#define W_TA_RIGHT 0x0002
+#define W_TA_CENTER 0x0006
+#define W_TA_TOP 0x0000
+#define W_TA_BOTTOM 0x0008
+#define W_TA_BASELINE 0x0018
+#define W_TA_RTLREADING 0x0100
+
+#define W_SRCCOPY 0x00CC0020L
+#define W_SRCPAINT 0x00EE0086L
+#define W_SRCAND 0x008800C6L
+#define W_SRCINVERT 0x00660046L
+#define W_SRCERASE 0x00440328L
+#define W_NOTSRCCOPY 0x00330008L
+#define W_NOTSRCERASE 0x001100A6L
+#define W_MERGECOPY 0x00C000CAL
+#define W_MERGEPAINT 0x00BB0226L
+#define W_PATCOPY 0x00F00021L
+#define W_PATPAINT 0x00FB0A09L
+#define W_PATINVERT 0x005A0049L
+#define W_DSTINVERT 0x00550009L
+#define W_BLACKNESS 0x00000042L
+#define W_WHITENESS 0x00FF0062L
+
+#define W_PS_SOLID 0
+#define W_PS_DASH 1
+#define W_PS_DOT 2
+#define W_PS_DASHDOT 3
+#define W_PS_DASHDOTDOT 4
+#define W_PS_NULL 5
+#define W_PS_INSIDEFRAME 6
+
+#define W_LF_FACESIZE 32
+
+#define W_ANSI_CHARSET 0
+#define W_DEFAULT_CHARSET 1
+#define W_SYMBOL_CHARSET 2
+#define W_SHIFTJIS_CHARSET 128
+#define W_HANGEUL_CHARSET 129
+#define W_GB2312_CHARSET 134
+#define W_CHINESEBIG5_CHARSET 136
+#define W_OEM_CHARSET 255
+/*WINVER >= 0x0400*/
+#define W_JOHAB_CHARSET 130
+#define W_HEBREW_CHARSET 177
+#define W_ARABIC_CHARSET 178
+#define W_GREEK_CHARSET 161
+#define W_TURKISH_CHARSET 162
+#define W_VIETNAMESE_CHARSET 163
+#define W_THAI_CHARSET 222
+#define W_EASTEUROPE_CHARSET 238
+#define W_RUSSIAN_CHARSET 204
+#define W_MAC_CHARSET 77
+#define W_BALTIC_CHARSET 186
+
+#define W_DEFAULT_PITCH 0x00
+#define W_FIXED_PITCH 0x01
+#define W_VARIABLE_PITCH 0x02
+
+#define W_FF_DONTCARE 0x00
+#define W_FF_ROMAN 0x10
+#define W_FF_SWISS 0x20
+#define W_FF_MODERN 0x30
+#define W_FF_SCRIPT 0x40
+#define W_FF_DECORATIVE 0x50
+
+#define W_FW_DONTCARE 0
+#define W_FW_THIN 100
+#define W_FW_EXTRALIGHT 200
+#define W_FW_LIGHT 300
+#define W_FW_NORMAL 400
+#define W_FW_MEDIUM 500
+#define W_FW_SEMIBOLD 600
+#define W_FW_BOLD 700
+#define W_FW_EXTRABOLD 800
+#define W_FW_HEAVY 900
+#define W_FW_ULTRALIGHT 200
+#define W_FW_REGULAR 400
+#define W_FW_DEMIBOLD 600
+#define W_FW_ULTRABOLD 800
+#define W_FW_BLACK 900
+
+#define W_BS_SOLID 0
+#define W_BS_HOLLOW 1
+#define W_BS_HATCHED 2
+#define W_BS_PATTERN 3
+#define W_BS_INDEXED 4
+#define W_BS_DIBPATTERN 5
+
+#define W_HS_HORIZONTAL 0
+#define W_HS_VERTICAL 1
+#define W_HS_FDIAGONAL 2
+#define W_HS_BDIAGONAL 3
+#define W_HS_CROSS 4
+#define W_HS_DIAGCROSS 5
+
+#define W_MFCOMMENT 15
+
+#define PRIVATE_ESCAPE_UNICODE 2
+
+//========================== Methoden von WMFWriter ==========================
+
+void WMFWriter::MayCallback()
+{
+ if ( xStatusIndicator.is() )
+ {
+ sal_uLong nPercent;
+
+ // Wir gehen mal einfach so davon aus, dass 16386 Actions einer Bitmap entsprechen
+ // (in der Regel wird ein Metafile entweder nur Actions oder einige Bitmaps und fast
+ // keine Actions enthalten. Dann ist das Verhaeltnis ziemlich unwichtig)
+
+ nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
+ *100
+ /((nNumberOfBitmaps<<14)+nNumberOfActions);
+
+ if ( nPercent >= nLastPercent + 3 )
+ {
+ nLastPercent = nPercent;
+ if( nPercent <= 100 )
+ xStatusIndicator->setValue( nPercent );
+ }
+ }
+}
+
+void WMFWriter::CountActionsAndBitmaps( const GDIMetaFile & rMTF )
+{
+ size_t nAction, nActionCount;
+
+ nActionCount = rMTF.GetActionSize();
+
+ for ( nAction=0; nAction < nActionCount; nAction++ )
+ {
+ MetaAction* pMA = rMTF.GetAction( nAction );
+
+ switch( pMA->GetType() )
+ {
+ case META_BMP_ACTION:
+ case META_BMPSCALE_ACTION:
+ case META_BMPSCALEPART_ACTION:
+ case META_BMPEX_ACTION:
+ case META_BMPEXSCALE_ACTION:
+ case META_BMPEXSCALEPART_ACTION:
+ nNumberOfBitmaps++;
+ break;
+ }
+ nNumberOfActions++;
+ }
+}
+
+
+void WMFWriter::WritePointXY(const Point & rPoint)
+{
+ Point aPt( pVirDev->LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
+ *pWMF << ((short)aPt.X()) << ((short)aPt.Y());
+}
+
+
+void WMFWriter::WritePointYX(const Point & rPoint)
+{
+ Point aPt( pVirDev->LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
+ *pWMF << ((short)aPt.Y()) << ((short)aPt.X());
+}
+
+
+sal_Int32 WMFWriter::ScaleWidth( sal_Int32 nDX )
+{
+ Size aSz( pVirDev->LogicToLogic(Size(nDX,0),aSrcMapMode,aTargetMapMode) );
+ return aSz.Width();
+}
+
+
+void WMFWriter::WriteSize(const Size & rSize)
+{
+ Size aSz( pVirDev->LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
+ *pWMF << ((short)aSz.Width()) << ((short)aSz.Height());
+}
+
+
+void WMFWriter::WriteHeightWidth(const Size & rSize)
+{
+ Size aSz( pVirDev->LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
+ *pWMF << ((short)aSz.Height()) << ((short)aSz.Width());
+}
+
+
+void WMFWriter::WriteRectangle(const Rectangle & rRect)
+{
+ WritePointYX(Point(rRect.Right()+1,rRect.Bottom()+1));
+ WritePointYX(rRect.TopLeft());
+}
+
+
+void WMFWriter::WriteColor(const Color & rColor)
+{
+ *pWMF << (sal_uInt8) rColor.GetRed() << (sal_uInt8) rColor.GetGreen() << (sal_uInt8) rColor.GetBlue() << (sal_uInt8) 0;
+}
+
+
+void WMFWriter::WriteRecordHeader(sal_uInt32 nSizeWords, sal_uInt16 nType)
+{
+ nActRecordPos=pWMF->Tell();
+ if (nSizeWords>nMaxRecordSize) nMaxRecordSize=nSizeWords;
+ *pWMF << nSizeWords << nType;
+}
+
+
+void WMFWriter::UpdateRecordHeader()
+{
+ sal_uLong nPos;
+ sal_uInt32 nSize;
+
+ nPos=pWMF->Tell(); nSize=nPos-nActRecordPos;
+ if ((nSize & 1)!=0) {
+ *pWMF << (sal_uInt8)0;
+ nPos++; nSize++;
+ }
+ nSize/=2;
+ if (nSize>nMaxRecordSize) nMaxRecordSize=nSize;
+ pWMF->Seek(nActRecordPos);
+ *pWMF << nSize;
+ pWMF->Seek(nPos);
+}
+
+
+void WMFWriter::WMFRecord_Arc(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
+{
+ WriteRecordHeader(0x0000000b,W_META_ARC);
+ WritePointYX(rEndPt);
+ WritePointYX(rStartPt);
+ WriteRectangle(rRect);
+}
+
+void WMFWriter::WMFRecord_Chord(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
+{
+ WriteRecordHeader(0x0000000b,W_META_CHORD);
+ WritePointYX(rEndPt);
+ WritePointYX(rStartPt);
+ WriteRectangle(rRect);
+}
+
+
+void WMFWriter::WMFRecord_CreateBrushIndirect(const Color& rColor)
+{
+ WriteRecordHeader(0x00000007,W_META_CREATEBRUSHINDIRECT);
+
+ if( rColor==Color(COL_TRANSPARENT) )
+ *pWMF << (sal_uInt16) W_BS_HOLLOW;
+ else
+ *pWMF << (sal_uInt16) W_BS_SOLID;
+
+ WriteColor( rColor );
+ *pWMF << (sal_uInt16) 0;
+}
+
+
+void WMFWriter::WMFRecord_CreateFontIndirect(const Font & rFont)
+{
+ sal_uInt16 nWeight,i;
+ sal_uInt8 nPitchFamily;
+
+ WriteRecordHeader(0x00000000,W_META_CREATEFONTINDIRECT);
+ WriteHeightWidth(Size(rFont.GetSize().Width(),-rFont.GetSize().Height()));
+ *pWMF << (short)rFont.GetOrientation() << (short)rFont.GetOrientation();
+
+ switch (rFont.GetWeight()) {
+ case WEIGHT_THIN: nWeight=W_FW_THIN; break;
+ case WEIGHT_ULTRALIGHT: nWeight=W_FW_ULTRALIGHT; break;
+ case WEIGHT_LIGHT: nWeight=W_FW_LIGHT; break;
+ case WEIGHT_SEMILIGHT: nWeight=W_FW_LIGHT; break;
+ case WEIGHT_NORMAL: nWeight=W_FW_NORMAL; break;
+ case WEIGHT_MEDIUM: nWeight=W_FW_MEDIUM; break;
+ case WEIGHT_SEMIBOLD: nWeight=W_FW_SEMIBOLD; break;
+ case WEIGHT_BOLD: nWeight=W_FW_BOLD; break;
+ case WEIGHT_ULTRABOLD: nWeight=W_FW_ULTRABOLD; break;
+ case WEIGHT_BLACK: nWeight=W_FW_BLACK; break;
+ default: nWeight=W_FW_DONTCARE;
+ }
+ *pWMF << nWeight;
+
+ if (rFont.GetItalic()==ITALIC_NONE) *pWMF << (sal_uInt8)0; else *pWMF << (sal_uInt8)1;
+ if (rFont.GetUnderline()==UNDERLINE_NONE) *pWMF << (sal_uInt8)0; else *pWMF << (sal_uInt8)1;
+ if (rFont.GetStrikeout()==STRIKEOUT_NONE) *pWMF << (sal_uInt8)0; else *pWMF << (sal_uInt8)1;
+
+ CharSet eFontNameEncoding = rFont.GetCharSet();
+ sal_uInt8 nCharSet = rtl_getBestWindowsCharsetFromTextEncoding( eFontNameEncoding );
+ if ( eFontNameEncoding == RTL_TEXTENCODING_SYMBOL )
+ eFontNameEncoding = RTL_TEXTENCODING_MS_1252;
+ if ( nCharSet == 1 )
+ nCharSet = W_ANSI_CHARSET;
+ *pWMF << nCharSet;
+
+ *pWMF << (sal_uInt8)0 << (sal_uInt8)0 << (sal_uInt8)0;
+
+ switch (rFont.GetPitch()) {
+ case PITCH_FIXED: nPitchFamily=W_FIXED_PITCH; break;
+ case PITCH_VARIABLE: nPitchFamily=W_VARIABLE_PITCH; break;
+ default: nPitchFamily=W_DEFAULT_PITCH;
+ }
+ switch (rFont.GetFamily()) {
+ case FAMILY_DECORATIVE: nPitchFamily|=W_FF_DECORATIVE; break;
+ case FAMILY_MODERN: nPitchFamily|=W_FF_MODERN; break;
+ case FAMILY_ROMAN: nPitchFamily|=W_FF_ROMAN; break;
+ case FAMILY_SCRIPT: nPitchFamily|=W_FF_SCRIPT; break;
+ case FAMILY_SWISS: nPitchFamily|=W_FF_SWISS; break;
+ default: nPitchFamily|=W_FF_DONTCARE;
+ }
+ *pWMF << nPitchFamily;
+
+ rtl::OString aFontName(rtl::OUStringToOString(rFont.GetName(), eFontNameEncoding));
+ for ( i = 0; i < W_LF_FACESIZE; i++ )
+ {
+ sal_Char nChar = ( i < aFontName.getLength() ) ? aFontName[i] : 0;
+ *pWMF << nChar;
+ }
+ UpdateRecordHeader();
+}
+
+void WMFWriter::WMFRecord_CreatePenIndirect(const Color& rColor, const LineInfo& rLineInfo )
+{
+ WriteRecordHeader(0x00000008,W_META_CREATEPENINDIRECT);
+ sal_uInt16 nStyle = rColor == Color( COL_TRANSPARENT ) ? W_PS_NULL : W_PS_SOLID;
+ switch( rLineInfo.GetStyle() )
+ {
+ case LINE_DASH :
+ {
+ if ( rLineInfo.GetDotCount() )
+ {
+ if ( !rLineInfo.GetDashCount() )
+ nStyle = W_PS_DOT;
+ else
+ {
+ if ( !rLineInfo.GetDotCount() == 1 )
+ nStyle = W_PS_DASHDOT;
+ else
+ nStyle = W_PS_DASHDOTDOT;
+ }
+ }
+ else
+ nStyle = W_PS_DASH;
+ }
+ break;
+ case LINE_NONE :
+ nStyle = W_PS_NULL;
+ break;
+ default:
+ break;
+ }
+ *pWMF << nStyle;
+
+ WriteSize( Size( rLineInfo.GetWidth(), 0 ) );
+ WriteColor( rColor );
+}
+
+void WMFWriter::WMFRecord_DeleteObject(sal_uInt16 nObjectHandle)
+{
+ WriteRecordHeader(0x00000004,W_META_DELETEOBJECT);
+ *pWMF << nObjectHandle;
+}
+
+
+void WMFWriter::WMFRecord_Ellipse(const Rectangle & rRect)
+{
+ WriteRecordHeader(0x00000007,W_META_ELLIPSE);
+ WriteRectangle(rRect);
+}
+
+bool IsStarSymbol(const String &rStr)
+{
+ return rStr.EqualsIgnoreCaseAscii("starsymbol") ||
+ rStr.EqualsIgnoreCaseAscii("opensymbol");
+}
+
+void WMFWriter::WMFRecord_Escape( sal_uInt32 nEsc, sal_uInt32 nLen, const sal_Int8* pData )
+{
+#ifdef OSL_BIGENDIAN
+ sal_uInt32 nTmp = OSL_SWAPDWORD( nEsc );
+ sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
+#else
+ sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
+#endif
+ if ( nLen )
+ nCheckSum = rtl_crc32( nCheckSum, pData, nLen );
+
+ WriteRecordHeader( 3 + 9 + ( ( nLen + 1 ) >> 1 ), W_META_ESCAPE );
+ *pWMF << (sal_uInt16)W_MFCOMMENT
+ << (sal_uInt16)( nLen + 14 ) // we will always have a fourteen byte escape header:
+ << (sal_uInt16)0x4f4f // OO
+ << (sal_uInt32)0xa2c2a // evil magic number
+ << (sal_uInt32)nCheckSum // crc32 checksum about nEsc & pData
+ << (sal_uInt32)nEsc; // escape number
+ pWMF->Write( pData, nLen );
+ if ( nLen & 1 )
+ *pWMF << (sal_uInt8)0; // pad byte
+}
+
+/* if return value is true, then a complete unicode string and also a polygon replacement has been written,
+ so there is no more action necessary
+*/
+sal_Bool WMFWriter::WMFRecord_Escape_Unicode( const Point& rPoint, const String& rUniStr, const sal_Int32* pDXAry )
+{
+ sal_Bool bEscapeUsed = sal_False;
+
+ sal_uInt32 i, nStringLen = rUniStr.Len();
+ if ( nStringLen )
+ {
+ // first we will check if a comment is necessary
+ if ( aSrcFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) // symbol is always byte character, so there is no unicode loss
+ {
+ const sal_Unicode* pBuf = rUniStr.GetBuffer();
+ const rtl_TextEncoding aTextEncodingOrg = aSrcFont.GetCharSet();
+ rtl::OString aByteStr(rtl::OUStringToOString(rUniStr, aTextEncodingOrg));
+ rtl::OUString aUniStr2(rtl::OStringToOUString(aByteStr, aTextEncodingOrg));
+ const sal_Unicode* pConversion = aUniStr2.getStr(); // this is the unicode array after bytestring <-> unistring conversion
+ for ( i = 0; i < nStringLen; i++ )
+ {
+ if ( *pBuf++ != *pConversion++ )
+ break;
+ }
+
+ if ( i != nStringLen ) // after conversion the characters are not original,
+ { // try again, with determining a better charset from unicode char
+ pBuf = rUniStr.GetBuffer();
+ const sal_Unicode* pCheckChar = pBuf;
+ rtl_TextEncoding aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the first character
+ for ( i = 1; i < nStringLen; i++)
+ {
+ if (aTextEncoding != aTextEncodingOrg) // found something
+ break;
+ pCheckChar++;
+ aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the next character
+ }
+
+ aByteStr = rtl::OUStringToOString(rUniStr, aTextEncoding);
+ aUniStr2 = rtl::OStringToOUString(aByteStr, aTextEncoding);
+ pConversion = aUniStr2.getStr(); // this is the unicode array after bytestring <-> unistring conversion
+ for ( i = 0; i < nStringLen; i++ )
+ {
+ if ( *pBuf++ != *pConversion++ )
+ break;
+ }
+ if (i == nStringLen)
+ {
+ aSrcFont.SetCharSet (aTextEncoding);
+ SetAllAttr();
+ }
+ }
+
+ if ( ( i != nStringLen ) || IsStarSymbol( aSrcFont.GetName() ) ) // after conversion the characters are not original, so we
+ { // will store the unicode string and a polypoly replacement
+ Color aOldFillColor( aSrcFillColor );
+ Color aOldLineColor( aSrcLineColor );
+ aSrcLineInfo = LineInfo();
+ aSrcFillColor = aSrcTextColor;
+ aSrcLineColor = Color( COL_TRANSPARENT );
+ SetLineAndFillAttr();
+ pVirDev->SetFont( aSrcFont );
+ std::vector<PolyPolygon> aPolyPolyVec;
+ if ( pVirDev->GetTextOutlines( aPolyPolyVec, rUniStr ) )
+ {
+ sal_uInt32 nDXCount = pDXAry ? nStringLen : 0;
+ sal_uInt32 nSkipActions = aPolyPolyVec.size();
+ sal_Int32 nStrmLen = 8 +
+ + sizeof( nStringLen ) + ( nStringLen * 2 )
+ + sizeof( nDXCount ) + ( nDXCount * 4 )
+ + sizeof( nSkipActions );
+
+ SvMemoryStream aMemoryStream( nStrmLen );
+ Point aPt( pVirDev->LogicToLogic( rPoint, aSrcMapMode, aTargetMapMode ) );
+ aMemoryStream << static_cast<sal_Int32>(aPt.X())
+ << static_cast<sal_Int32>(aPt.Y())
+ << nStringLen;
+ for ( i = 0; i < nStringLen; i++ )
+ aMemoryStream << rUniStr.GetChar( (sal_uInt16)i );
+ aMemoryStream << nDXCount;
+ for ( i = 0; i < nDXCount; i++ )
+ aMemoryStream << pDXAry[ i ];
+ aMemoryStream << nSkipActions;
+ WMFRecord_Escape( PRIVATE_ESCAPE_UNICODE, nStrmLen, (const sal_Int8*)aMemoryStream.GetData() );
+
+ std::vector<PolyPolygon>::iterator aIter( aPolyPolyVec.begin() );
+ while ( aIter != aPolyPolyVec.end() )
+ {
+ PolyPolygon aPolyPoly( *aIter++ );
+ aPolyPoly.Move( rPoint.X(), rPoint.Y() );
+ WMFRecord_PolyPolygon( aPolyPoly );
+ }
+ aSrcFillColor = aOldFillColor;
+ aSrcLineColor = aOldLineColor;
+ bEscapeUsed = sal_True;
+ }
+ }
+ }
+ }
+ return bEscapeUsed;
+}
+
+void WMFWriter::WMFRecord_ExtTextOut( const Point & rPoint,
+ const String & rString, const sal_Int32 * pDXAry )
+{
+ sal_uInt16 nOriginalTextLen = rString.Len();
+
+ if ( (nOriginalTextLen <= 1) || (pDXAry == NULL) )
+ {
+ WMFRecord_TextOut(rPoint, rString);
+ return;
+ }
+ rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
+ rtl::OString aByteString(rtl::OUStringToOString(rString, eChrSet));
+ TrueExtTextOut(rPoint,rString,aByteString,pDXAry);
+}
+
+void WMFWriter::TrueExtTextOut( const Point & rPoint, const String & rString,
+ const rtl::OString& rByteString, const sal_Int32 * pDXAry )
+{
+ WriteRecordHeader( 0, W_META_EXTTEXTOUT );
+ WritePointYX( rPoint );
+ sal_uInt16 nNewTextLen = static_cast<sal_uInt16>(rByteString.getLength());
+ *pWMF << nNewTextLen << (sal_uInt16)0;
+ write_uInt8s_FromOString(*pWMF, rByteString, nNewTextLen);
+ if ( nNewTextLen & 1 )
+ *pWMF << (sal_uInt8)0;
+
+ sal_uInt16 nOriginalTextLen = rString.Len();
+ sal_Int16* pConvertedDXAry = new sal_Int16[ nOriginalTextLen ];
+ sal_Int32 j = 0;
+ pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ 0 ] );
+ for (sal_uInt16 i = 1; i < ( nOriginalTextLen - 1 ); ++i)
+ pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ i ] - pDXAry[ i - 1 ] );
+ pConvertedDXAry[ j ] = (sal_Int16)ScaleWidth( pDXAry[ nOriginalTextLen - 2 ] / ( nOriginalTextLen - 1 ) );
+
+ for (sal_uInt16 i = 0; i < nOriginalTextLen; ++i)
+ {
+ sal_Int16 nDx = pConvertedDXAry[ i ];
+ *pWMF << nDx;
+ if ( nOriginalTextLen < nNewTextLen )
+ {
+ sal_Unicode nUniChar = rString.GetChar(i);
+ rtl::OString aTemp(&nUniChar, 1, aSrcFont.GetCharSet());
+ j = aTemp.getLength();
+ while ( --j > 0 )
+ *pWMF << (sal_uInt16)0;
+ }
+ }
+ delete[] pConvertedDXAry;
+ UpdateRecordHeader();
+}
+
+void WMFWriter::WMFRecord_LineTo(const Point & rPoint)
+{
+ WriteRecordHeader(0x00000005,W_META_LINETO);
+ WritePointYX(rPoint);
+}
+
+
+void WMFWriter::WMFRecord_MoveTo(const Point & rPoint)
+{
+ WriteRecordHeader(0x00000005,W_META_MOVETO);
+ WritePointYX(rPoint);
+}
+
+
+void WMFWriter::WMFRecord_Pie(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
+{
+ WriteRecordHeader(0x0000000b,W_META_PIE);
+ WritePointYX(rEndPt);
+ WritePointYX(rStartPt);
+ WriteRectangle(rRect);
+}
+
+
+void WMFWriter::WMFRecord_Polygon(const Polygon & rPoly)
+{
+ sal_uInt16 nSize,i;
+
+ Polygon aSimplePoly;
+ if ( rPoly.HasFlags() )
+ rPoly.AdaptiveSubdivide( aSimplePoly );
+ else
+ aSimplePoly = rPoly;
+ nSize = aSimplePoly.GetSize();
+ WriteRecordHeader(((sal_uLong)nSize)*2+4,W_META_POLYGON);
+ *pWMF << nSize;
+ for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
+}
+
+
+void WMFWriter::WMFRecord_PolyLine(const Polygon & rPoly)
+{
+ sal_uInt16 nSize,i;
+ Polygon aSimplePoly;
+ if ( rPoly.HasFlags() )
+ rPoly.AdaptiveSubdivide( aSimplePoly );
+ else
+ aSimplePoly = rPoly;
+ nSize=aSimplePoly.GetSize();
+ WriteRecordHeader(((sal_uLong)nSize)*2+4,W_META_POLYLINE);
+ *pWMF << nSize;
+ for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
+}
+
+
+void WMFWriter::WMFRecord_PolyPolygon(const PolyPolygon & rPolyPoly)
+{
+ const Polygon * pPoly;
+ sal_uInt16 nCount,nSize,i,j;
+
+ nCount=rPolyPoly.Count();
+ PolyPolygon aSimplePolyPoly( rPolyPoly );
+ for ( i = 0; i < nCount; i++ )
+ {
+ if ( aSimplePolyPoly[ i ].HasFlags() )
+ {
+ Polygon aSimplePoly;
+ aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly );
+ aSimplePolyPoly[ i ] = aSimplePoly;
+ }
+ }
+ WriteRecordHeader(0,W_META_POLYPOLYGON);
+ *pWMF << nCount;
+ for (i=0; i<nCount; i++) *pWMF << ((sal_uInt16)(aSimplePolyPoly.GetObject(i).GetSize()));
+ for (i=0; i<nCount; i++) {
+ pPoly=&(aSimplePolyPoly.GetObject(i));
+ nSize=pPoly->GetSize();
+ for (j=0; j<nSize; j++) WritePointXY(pPoly->GetPoint(j));
+ }
+ UpdateRecordHeader();
+}
+
+
+void WMFWriter::WMFRecord_Rectangle(const Rectangle & rRect)
+{
+ WriteRecordHeader( 0x00000007,W_META_RECTANGLE );
+ WriteRectangle( rRect );
+}
+
+
+void WMFWriter::WMFRecord_RestoreDC()
+{
+ WriteRecordHeader(0x00000004,W_META_RESTOREDC);
+ *pWMF << (short)-1;
+}
+
+
+void WMFWriter::WMFRecord_RoundRect(const Rectangle & rRect, long nHorzRound, long nVertRound)
+{
+ WriteRecordHeader(0x00000009,W_META_ROUNDRECT);
+ WriteHeightWidth(Size(nHorzRound,nVertRound));
+ WriteRectangle(rRect);
+}
+
+
+void WMFWriter::WMFRecord_SaveDC()
+{
+ WriteRecordHeader(0x00000003,W_META_SAVEDC);
+}
+
+
+void WMFWriter::WMFRecord_SelectObject(sal_uInt16 nObjectHandle)
+{
+ WriteRecordHeader(0x00000004,W_META_SELECTOBJECT);
+ *pWMF << nObjectHandle;
+}
+
+
+void WMFWriter::WMFRecord_SetBkMode(sal_Bool bTransparent)
+{
+ WriteRecordHeader(0x00000004,W_META_SETBKMODE);
+ if (bTransparent==sal_True) *pWMF << (sal_uInt16)W_TRANSPARENT;
+ else *pWMF << (sal_uInt16)W_OPAQUE;
+}
+
+void WMFWriter::WMFRecord_SetStretchBltMode()
+{
+ WriteRecordHeader( 0x00000004, W_META_SETSTRETCHBLTMODE );
+ *pWMF << (sal_uInt16) 3; // STRETCH_DELETESCANS
+}
+
+void WMFWriter::WMFRecord_SetPixel(const Point & rPoint, const Color & rColor)
+{
+ WriteRecordHeader(0x00000007,W_META_SETPIXEL);
+ WriteColor(rColor);
+ WritePointYX(rPoint);
+}
+
+
+void WMFWriter::WMFRecord_SetROP2(RasterOp eROP)
+{
+ sal_uInt16 nROP2;
+
+ switch (eROP) {
+ case ROP_INVERT: nROP2=W_R2_NOT; break;
+ case ROP_XOR: nROP2=W_R2_XORPEN; break;
+ default: nROP2=W_R2_COPYPEN;
+ }
+ WriteRecordHeader(0x00000004,W_META_SETROP2);
+ *pWMF << nROP2;
+}
+
+
+void WMFWriter::WMFRecord_SetTextAlign(FontAlign eFontAlign, sal_uInt32 eHorTextAlign)
+{
+ sal_uInt16 nAlign;
+
+ switch (eFontAlign) {
+ case ALIGN_TOP: nAlign=W_TA_TOP; break;
+ case ALIGN_BOTTOM: nAlign=W_TA_BOTTOM; break;
+ default: nAlign=W_TA_BASELINE;
+ }
+ nAlign|=eHorTextAlign;
+ nAlign|=W_TA_NOUPDATECP;
+
+ WriteRecordHeader(0x00000004,W_META_SETTEXTALIGN);
+ *pWMF << nAlign;
+}
+
+
+void WMFWriter::WMFRecord_SetTextColor(const Color & rColor)
+{
+ WriteRecordHeader(0x00000005,W_META_SETTEXTCOLOR);
+ WriteColor(rColor);
+}
+
+
+void WMFWriter::WMFRecord_SetWindowExt(const Size & rSize)
+{
+ WriteRecordHeader(0x00000005,W_META_SETWINDOWEXT);
+ WriteHeightWidth(rSize);
+}
+
+
+void WMFWriter::WMFRecord_SetWindowOrg(const Point & rPoint)
+{
+ WriteRecordHeader(0x00000005,W_META_SETWINDOWORG);
+ WritePointYX(rPoint);
+}
+
+
+void WMFWriter::WMFRecord_StretchDIB( const Point & rPoint, const Size & rSize,
+ const Bitmap & rBitmap, sal_uInt32 nROP )
+{
+ sal_uLong nPosAnf,nPosEnd;
+
+ nActBitmapPercent=50;
+ MayCallback();
+
+ WriteRecordHeader(0x00000000,W_META_STRETCHDIB);
+
+ // Die Reihenfolge im Metafile soll jetzt sein:
+ // einige Parameter (laenge 22), dann die Bitmap ohne FILEHEADER.
+ // Da aber *pWMF << rBitmap einen FILEHEADER der Laenge 14
+ // erzeugt, schreiben wir zuerst die Bitmap an die richtige Position
+ // Und ueberschreiben hinterher den FILEHEADER mit den Parametern.
+ nPosAnf=pWMF->Tell(); // Position merken, wo Parameter hin sollen
+ *pWMF << (sal_Int32)0 << (sal_Int32)0; // 8 bytes auffuellen (diese 8 bytes +
+ // 14 bytes ueberfluessigen FILEHEADER
+ // = 22 bytes Parameter)
+ *pWMF << rBitmap; // Bitmap schreiben
+
+ // Parameter schreiben:
+ nPosEnd=pWMF->Tell();
+ pWMF->Seek(nPosAnf);
+
+ // Raster-Op bestimmen, falls nichts uebergeben wurde
+ if( !nROP )
+ {
+ switch( eSrcRasterOp )
+ {
+ case ROP_INVERT: nROP = W_DSTINVERT; break;
+ case ROP_XOR: nROP = W_SRCINVERT; break;
+ default: nROP = W_SRCCOPY;
+ }
+ }
+
+ *pWMF << nROP <<
+ (short) 0 <<
+ (short) rBitmap.GetSizePixel().Height() <<
+ (short) rBitmap.GetSizePixel().Width() <<
+ (short) 0 <<
+ (short) 0;
+
+ WriteHeightWidth(rSize);
+ WritePointYX(rPoint);
+ pWMF->Seek(nPosEnd);
+
+ UpdateRecordHeader();
+
+ nWrittenBitmaps++;
+ nActBitmapPercent=0;
+}
+
+
+void WMFWriter::WMFRecord_TextOut(const Point & rPoint, const String & rStr)
+{
+ rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
+ rtl::OString aString(rtl::OUStringToOString(rStr, eChrSet));
+ TrueTextOut(rPoint, aString);
+}
+
+void WMFWriter::TrueTextOut(const Point & rPoint, const rtl::OString& rString)
+{
+ WriteRecordHeader(0,W_META_TEXTOUT);
+
+ write_lenPrefixed_uInt8s_FromOString<sal_uInt16>(*pWMF, rString);
+ sal_Int32 nLen = rString.getLength();
+ if ((nLen&1)!=0) *pWMF << (sal_uInt8)0;
+ WritePointYX(rPoint);
+ UpdateRecordHeader();
+}
+
+void WMFWriter::WMFRecord_EndOfFile()
+{
+ WriteRecordHeader(0x00000003,0x0000);
+}
+
+
+void WMFWriter::WMFRecord_IntersectClipRect( const Rectangle& rRect )
+{
+ WriteRecordHeader( 0x00000007, W_META_INTERSECTCLIPRECT );
+ WriteRectangle(rRect);
+}
+
+
+sal_uInt16 WMFWriter::AllocHandle()
+{
+ sal_uInt16 i;
+
+ for (i=0; i<MAXOBJECTHANDLES; i++) {
+ if (bHandleAllocated[i]==sal_False) {
+ bHandleAllocated[i]=sal_True;
+ return i;
+ }
+ }
+ bStatus=sal_False;
+ return 0xffff;
+}
+
+
+void WMFWriter::FreeHandle(sal_uInt16 nObjectHandle)
+{
+ if (nObjectHandle<MAXOBJECTHANDLES) bHandleAllocated[nObjectHandle]=sal_False;
+}
+
+
+void WMFWriter::CreateSelectDeletePen( const Color& rColor, const LineInfo& rLineInfo )
+{
+ sal_uInt16 nOldHandle;
+
+ nOldHandle=nDstPenHandle;
+ nDstPenHandle=AllocHandle();
+ WMFRecord_CreatePenIndirect( rColor, rLineInfo );
+ WMFRecord_SelectObject(nDstPenHandle);
+ if (nOldHandle<MAXOBJECTHANDLES) {
+ WMFRecord_DeleteObject(nOldHandle);
+ FreeHandle(nOldHandle);
+ }
+}
+
+
+void WMFWriter::CreateSelectDeleteFont(const Font & rFont)
+{
+ sal_uInt16 nOldHandle;
+
+ nOldHandle=nDstFontHandle;
+ nDstFontHandle=AllocHandle();
+ WMFRecord_CreateFontIndirect(rFont);
+ WMFRecord_SelectObject(nDstFontHandle);
+ if (nOldHandle<MAXOBJECTHANDLES) {
+ WMFRecord_DeleteObject(nOldHandle);
+ FreeHandle(nOldHandle);
+ }
+}
+
+
+void WMFWriter::CreateSelectDeleteBrush(const Color& rColor)
+{
+ sal_uInt16 nOldHandle;
+
+ nOldHandle=nDstBrushHandle;
+ nDstBrushHandle=AllocHandle();
+ WMFRecord_CreateBrushIndirect(rColor);
+ WMFRecord_SelectObject(nDstBrushHandle);
+ if (nOldHandle<MAXOBJECTHANDLES) {
+ WMFRecord_DeleteObject(nOldHandle);
+ FreeHandle(nOldHandle);
+ }
+}
+
+
+void WMFWriter::SetLineAndFillAttr()
+{
+ if ( eDstROP2 != eSrcRasterOp )
+ {
+ eDstROP2=eSrcRasterOp;
+ WMFRecord_SetROP2(eDstROP2);
+ }
+ if ( ( aDstLineColor != aSrcLineColor ) || ( aDstLineInfo != aSrcLineInfo ) )
+ {
+ aDstLineColor = aSrcLineColor;
+ aDstLineInfo = aSrcLineInfo;
+ CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
+ }
+ if ( aDstFillColor != aSrcFillColor )
+ {
+ aDstFillColor = aSrcFillColor;
+ CreateSelectDeleteBrush( aDstFillColor );
+ }
+ if ( bDstIsClipping != bSrcIsClipping ||
+ (bSrcIsClipping==sal_True && aDstClipRegion!=aSrcClipRegion)) {
+ bDstIsClipping=bSrcIsClipping;
+ aDstClipRegion=aSrcClipRegion;
+ }
+}
+
+void WMFWriter::SetAllAttr()
+{
+ SetLineAndFillAttr();
+ if ( aDstTextColor != aSrcTextColor )
+ {
+ aDstTextColor = aSrcTextColor;
+ WMFRecord_SetTextColor(aDstTextColor);
+ }
+ if ( eDstTextAlign != eSrcTextAlign || eDstHorTextAlign != eSrcHorTextAlign )
+ {
+ eDstTextAlign = eSrcTextAlign;
+ eDstHorTextAlign = eSrcHorTextAlign;
+ WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
+ }
+ if ( aDstFont != aSrcFont )
+ {
+ pVirDev->SetFont(aSrcFont);
+ if ( aDstFont.GetName() != aSrcFont.GetName() )
+ {
+ FontCharMap aFontCharMap;
+ if ( pVirDev->GetFontCharMap( aFontCharMap ) )
+ {
+ if ( ( aFontCharMap.GetFirstChar() & 0xff00 ) == 0xf000 )
+ aSrcFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
+ else if ( aSrcFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
+ aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
+ }
+ }
+ aDstFont = aSrcFont;
+ CreateSelectDeleteFont(aDstFont);
+ }
+}
+
+
+void WMFWriter::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())
+ {
+ aSrcLineInfo = rInfo;
+ SetLineAndFillAttr();
+
+ for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
+ {
+ const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
+ WMFRecord_PolyLine(Polygon(aCandidate));
+ }
+ }
+
+ if(aFillPolyPolygon.count())
+ {
+ const Color aOldLineColor(aSrcLineColor);
+ const Color aOldFillColor(aSrcFillColor);
+
+ aSrcLineColor = Color( COL_TRANSPARENT );
+ aSrcFillColor = aOldLineColor;
+ SetLineAndFillAttr();
+
+ for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
+ {
+ const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
+ WMFRecord_Polygon(Polygon(aPolygon));
+ }
+
+ aSrcLineColor = aOldLineColor;
+ aSrcFillColor = aOldFillColor;
+ SetLineAndFillAttr();
+ }
+ }
+}
+
+void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
+{
+ MetaAction* pMA;
+
+ if( bStatus )
+ {
+ size_t nACount = rMTF.GetActionSize();
+
+ WMFRecord_SetStretchBltMode();
+
+ for( size_t nA = 0; nA < nACount; nA++ )
+ {
+ pMA = rMTF.GetAction( nA );
+
+ switch( pMA->GetType() )
+ {
+ case META_PIXEL_ACTION:
+ {
+ const MetaPixelAction* pA = (const MetaPixelAction *) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_SetPixel( pA->GetPoint(), pA->GetColor() );
+ }
+ break;
+
+ case META_POINT_ACTION:
+ {
+ const MetaPointAction* pA = (const MetaPointAction*) pMA;
+ const Point& rPt = pA->GetPoint();
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_MoveTo( rPt);
+ WMFRecord_LineTo( rPt );
+ }
+ break;
+
+ case META_LINE_ACTION:
+ {
+ const MetaLineAction* pA = (const MetaLineAction *) pMA;
+ if(pA->GetLineInfo().IsDefault())
+ {
+ aSrcLineInfo = pA->GetLineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_MoveTo( pA->GetStartPoint() );
+ WMFRecord_LineTo( pA->GetEndPoint() );
+ }
+ 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()));
+ HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
+ }
+ }
+ break;
+
+ case META_RECT_ACTION:
+ {
+ const MetaRectAction* pA = (const MetaRectAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Rectangle( pA->GetRect() );
+ }
+ break;
+
+ case META_ROUNDRECT_ACTION:
+ {
+ const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_RoundRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
+ }
+ break;
+
+ case META_ELLIPSE_ACTION:
+ {
+ const MetaEllipseAction* pA = (const MetaEllipseAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Ellipse( pA->GetRect() );
+ }
+ break;
+
+ case META_ARC_ACTION:
+ {
+ const MetaArcAction* pA = (const MetaArcAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Arc( pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint() );
+ }
+ break;
+
+ case META_PIE_ACTION:
+ {
+ const MetaPieAction* pA = (const MetaPieAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Pie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
+ }
+ break;
+
+
+ case META_CHORD_ACTION:
+ {
+ const MetaChordAction* pA = (const MetaChordAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Chord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
+ }
+ break;
+
+ case META_POLYLINE_ACTION:
+ {
+ const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pMA;
+ const Polygon& rPoly = pA->GetPolygon();
+
+ if( rPoly.GetSize() )
+ {
+ if(pA->GetLineInfo().IsDefault())
+ {
+ aSrcLineInfo = pA->GetLineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_PolyLine( rPoly );
+ }
+ else
+ {
+ // LineInfo used; handle Dash/Dot and fat lines
+ HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
+ }
+ }
+ }
+ break;
+
+ case META_POLYGON_ACTION:
+ {
+ const MetaPolygonAction* pA = (const MetaPolygonAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Polygon( pA->GetPolygon() );
+ }
+ break;
+
+ case META_POLYPOLYGON_ACTION:
+ {
+ const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_PolyPolygon( pA->GetPolyPolygon() );
+ }
+ break;
+
+ case META_TEXTRECT_ACTION:
+ {
+ const MetaTextRectAction * pA = (const MetaTextRectAction*)pMA;
+ String aTemp( pA->GetText() );
+ aSrcLineInfo = LineInfo();
+ SetAllAttr();
+
+ Point aPos( pA->GetRect().TopLeft() );
+ if ( !WMFRecord_Escape_Unicode( aPos, aTemp, NULL ) )
+ WMFRecord_TextOut( aPos, aTemp );
+ }
+ break;
+
+ case META_TEXT_ACTION:
+ {
+ const MetaTextAction * pA = (const MetaTextAction*) pMA;
+ String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+ aSrcLineInfo = LineInfo();
+ SetAllAttr();
+ if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, NULL ) )
+ WMFRecord_TextOut( pA->GetPoint(), aTemp );
+ }
+ break;
+
+ case META_TEXTARRAY_ACTION:
+ {
+ const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pMA;
+
+ String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+ aSrcLineInfo = LineInfo();
+ SetAllAttr();
+ if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pA->GetDXArray() ) )
+ WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pA->GetDXArray() );
+ }
+ break;
+
+ case META_STRETCHTEXT_ACTION:
+ {
+ const MetaStretchTextAction* pA = (const MetaStretchTextAction *) pMA;
+ String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+
+ sal_uInt16 nLen,i;
+ sal_Int32 nNormSize;
+
+ pVirDev->SetFont( aSrcFont );
+ nLen = aTemp.Len();
+ sal_Int32* pDXAry = nLen ? new sal_Int32[ nLen ] : NULL;
+ nNormSize = pVirDev->GetTextArray( aTemp, pDXAry );
+ for ( i = 0; i < ( nLen - 1 ); i++ )
+ pDXAry[ i ] = pDXAry[ i ] * (sal_Int32)pA->GetWidth() / nNormSize;
+ if ( ( nLen <= 1 ) || ( (sal_Int32)pA->GetWidth() == nNormSize ) )
+ delete[] pDXAry, pDXAry = NULL;
+ aSrcLineInfo = LineInfo();
+ SetAllAttr();
+ if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pDXAry ) )
+ WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pDXAry );
+ delete[] pDXAry;
+ }
+ break;
+
+ case META_BMP_ACTION:
+ {
+ const MetaBmpAction* pA = (const MetaBmpAction *) pMA;
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetBitmap().GetSizePixel(), pA->GetBitmap() );
+ }
+ break;
+
+ case META_BMPSCALE_ACTION:
+ {
+ const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pMA;
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pA->GetBitmap() );
+ }
+ break;
+
+ case META_BMPSCALEPART_ACTION:
+ {
+ const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pMA;
+ Bitmap aTmp( pA->GetBitmap() );
+
+ if( aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
+ WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aTmp );
+ }
+ break;
+
+ case META_BMPEX_ACTION:
+ {
+ const MetaBmpExAction* pA = (const MetaBmpExAction *) pMA;
+ Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
+ Bitmap aMsk( pA->GetBitmapEx().GetMask() );
+
+ if( !!aMsk )
+ {
+ aBmp.Replace( aMsk, COL_WHITE );
+ aMsk.Invert();
+ WMFRecord_StretchDIB( pA->GetPoint(), aMsk.GetSizePixel(), aBmp, W_SRCPAINT );
+ WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp, W_SRCAND );
+ }
+ else
+ WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp );
+ }
+ break;
+
+ case META_BMPEXSCALE_ACTION:
+ {
+ const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pMA;
+ Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
+ Bitmap aMsk( pA->GetBitmapEx().GetMask() );
+
+ if( !!aMsk )
+ {
+ aBmp.Replace( aMsk, COL_WHITE );
+ aMsk.Invert();
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aMsk, W_SRCPAINT );
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp, W_SRCAND );
+ }
+ else
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp );
+ }
+ break;
+
+ case META_BMPEXSCALEPART_ACTION:
+ {
+ const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pMA;
+ 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();
+ WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aMsk, W_SRCPAINT );
+ WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp, W_SRCAND );
+ }
+ else
+ WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
+ }
+ break;
+
+ case META_GRADIENT_ACTION:
+ {
+ const MetaGradientAction* pA = (const MetaGradientAction*) pMA;
+ GDIMetaFile aTmpMtf;
+
+ pVirDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
+ WriteRecords( aTmpMtf );
+ }
+ break;
+
+ case META_HATCH_ACTION:
+ {
+ const MetaHatchAction* pA = (const MetaHatchAction*) pMA;
+ GDIMetaFile aTmpMtf;
+
+ pVirDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
+ WriteRecords( aTmpMtf );
+ }
+ break;
+
+ case META_WALLPAPER_ACTION:
+ {
+ const MetaWallpaperAction* pA = (const MetaWallpaperAction*) pMA;
+ const Color& rColor = pA->GetWallpaper().GetColor();
+ const Color aOldLineColor( aSrcLineColor );
+ const Color aOldFillColor( aSrcFillColor );
+
+ aSrcLineColor = rColor;
+ aSrcFillColor = rColor;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Rectangle( pA->GetRect() );
+ aSrcLineColor = aOldLineColor;
+ aSrcFillColor = aOldFillColor;
+ }
+ break;
+
+ case META_ISECTRECTCLIPREGION_ACTION:
+ {
+ const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA;
+ WMFRecord_IntersectClipRect( pA->GetRect() );
+ }
+ break;
+
+ case META_LINECOLOR_ACTION:
+ {
+ const MetaLineColorAction* pA = (const MetaLineColorAction*) pMA;
+
+ if( pA->IsSetting() )
+ aSrcLineColor = pA->GetColor();
+ else
+ aSrcLineColor = Color( COL_TRANSPARENT );
+ }
+ break;
+
+ case META_FILLCOLOR_ACTION:
+ {
+ const MetaFillColorAction* pA = (const MetaFillColorAction*) pMA;
+
+ if( pA->IsSetting() )
+ aSrcFillColor = pA->GetColor();
+ else
+ aSrcFillColor = Color( COL_TRANSPARENT );
+ }
+ break;
+
+ case META_TEXTCOLOR_ACTION:
+ {
+ const MetaTextColorAction* pA = (const MetaTextColorAction*) pMA;
+ aSrcTextColor = pA->GetColor();
+ }
+ break;
+
+ case META_TEXTFILLCOLOR_ACTION:
+ {
+ const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pMA;
+ if( pA->IsSetting() )
+ aSrcFont.SetFillColor( pA->GetColor() );
+ else
+ aSrcFont.SetFillColor( Color( COL_TRANSPARENT ) );
+ }
+ break;
+
+ case META_TEXTALIGN_ACTION:
+ {
+ const MetaTextAlignAction* pA = (const MetaTextAlignAction*) pMA;
+ eSrcTextAlign = pA->GetTextAlign();
+ }
+ break;
+
+ case META_MAPMODE_ACTION:
+ {
+ const MetaMapModeAction* pA = (const MetaMapModeAction*) pMA;
+
+ if (aSrcMapMode!=pA->GetMapMode())
+ {
+ if( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE )
+ {
+ MapMode aMM = pA->GetMapMode();
+ Fraction aScaleX = aMM.GetScaleX();
+ Fraction aScaleY = aMM.GetScaleY();
+
+ Point aOrigin = aSrcMapMode.GetOrigin();
+ BigInt aX( aOrigin.X() );
+ aX *= BigInt( aScaleX.GetDenominator() );
+ if( aOrigin.X() >= 0 )
+ if( aScaleX.GetNumerator() >= 0 )
+ aX += BigInt( aScaleX.GetNumerator()/2 );
+ else
+ aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
+ else
+ if( aScaleX.GetNumerator() >= 0 )
+ aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
+ else
+ aX += BigInt( aScaleX.GetNumerator()/2 );
+ aX /= BigInt( aScaleX.GetNumerator() );
+ aOrigin.X() = (long)aX + aMM.GetOrigin().X();
+ BigInt aY( aOrigin.Y() );
+ aY *= BigInt( aScaleY.GetDenominator() );
+ if( aOrigin.Y() >= 0 )
+ if( aScaleY.GetNumerator() >= 0 )
+ aY += BigInt( aScaleY.GetNumerator()/2 );
+ else
+ aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
+ else
+ if( aScaleY.GetNumerator() >= 0 )
+ aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
+ else
+ aY += BigInt( aScaleY.GetNumerator()/2 );
+ aY /= BigInt( aScaleY.GetNumerator() );
+ aOrigin.Y() = (long)aY + aMM.GetOrigin().Y();
+ aSrcMapMode.SetOrigin( aOrigin );
+
+ aScaleX *= aSrcMapMode.GetScaleX();
+ aScaleY *= aSrcMapMode.GetScaleY();
+ aSrcMapMode.SetScaleX( aScaleX );
+ aSrcMapMode.SetScaleY( aScaleY );
+ }
+ else
+ aSrcMapMode=pA->GetMapMode();
+ }
+ }
+ break;
+
+ case META_FONT_ACTION:
+ {
+ const MetaFontAction* pA = (const MetaFontAction*) pMA;
+ aSrcFont = pA->GetFont();
+
+ if ( (aSrcFont.GetCharSet() == RTL_TEXTENCODING_DONTKNOW)
+ || (aSrcFont.GetCharSet() == RTL_TEXTENCODING_UNICODE) )
+ {
+ aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
+ }
+ eSrcTextAlign = aSrcFont.GetAlign();
+ aSrcTextColor = aSrcFont.GetColor();
+ aSrcFont.SetAlign( ALIGN_BASELINE );
+ aSrcFont.SetColor( COL_WHITE );
+ }
+ break;
+
+ case META_PUSH_ACTION:
+ {
+ const MetaPushAction* pA = (const MetaPushAction*)pMA;
+
+ WMFWriterAttrStackMember* pAt = new WMFWriterAttrStackMember;
+ pAt->nFlags = pA->GetFlags();
+ pAt->aClipRegion = aSrcClipRegion;
+ pAt->aLineColor=aSrcLineColor;
+ pAt->aFillColor=aSrcFillColor;
+ pAt->eRasterOp=eSrcRasterOp;
+ pAt->aFont=aSrcFont;
+ pAt->eTextAlign=eSrcTextAlign;
+ pAt->aTextColor=aSrcTextColor;
+ pAt->aMapMode=aSrcMapMode;
+ pAt->aLineInfo=aDstLineInfo;
+ pAt->pSucc=pAttrStack;
+ pAttrStack=pAt;
+
+ SetAllAttr(); // update ( now all source attributes are equal to the destination attributes )
+ WMFRecord_SaveDC();
+
+ }
+ break;
+
+ case META_POP_ACTION:
+ {
+ WMFWriterAttrStackMember * pAt=pAttrStack;
+
+ if( pAt )
+ {
+ aDstLineInfo = pAt->aLineInfo;
+ aDstLineColor = pAt->aLineColor;
+ if ( pAt->nFlags & PUSH_LINECOLOR )
+ aSrcLineColor = pAt->aLineColor;
+ aDstFillColor = pAt->aFillColor;
+ if ( pAt->nFlags & PUSH_FILLCOLOR )
+ aSrcFillColor = pAt->aFillColor;
+ eDstROP2 = pAt->eRasterOp;
+ if ( pAt->nFlags & PUSH_RASTEROP )
+ eSrcRasterOp = pAt->eRasterOp;
+ aDstFont = pAt->aFont;
+ if ( pAt->nFlags & PUSH_FONT )
+ aSrcFont = pAt->aFont;
+ eDstTextAlign = pAt->eTextAlign;
+ if ( pAt->nFlags & ( PUSH_FONT | PUSH_TEXTALIGN ) )
+ eSrcTextAlign = pAt->eTextAlign;
+ aDstTextColor = pAt->aTextColor;
+ if ( pAt->nFlags & ( PUSH_FONT | PUSH_TEXTCOLOR ) )
+ aSrcTextColor = pAt->aTextColor;
+ if ( pAt->nFlags & PUSH_MAPMODE )
+ aSrcMapMode = pAt->aMapMode;
+ aDstClipRegion = pAt->aClipRegion;
+ if ( pAt->nFlags & PUSH_CLIPREGION )
+ aSrcClipRegion = pAt->aClipRegion;
+
+ WMFRecord_RestoreDC();
+ pAttrStack = pAt->pSucc;
+ delete pAt;
+ }
+ }
+ break;
+
+ case META_EPS_ACTION :
+ {
+ const MetaEPSAction* pA = (const MetaEPSAction*)pMA;
+ const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
+
+ size_t nCount = aGDIMetaFile.GetActionSize();
+ for ( size_t i = 0; i < nCount; i++ )
+ {
+ const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
+ if ( pMetaAct->GetType() == META_BMPSCALE_ACTION )
+ {
+ const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*)pMetaAct;
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap() );
+ break;
+ }
+ }
+ }
+ break;
+
+ case META_RASTEROP_ACTION:
+ {
+ const MetaRasterOpAction* pA = (const MetaRasterOpAction*) pMA;
+ eSrcRasterOp=pA->GetRasterOp();
+ }
+ break;
+
+ case META_TRANSPARENT_ACTION:
+ {
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_PolyPolygon( ( (MetaTransparentAction*) pMA )->GetPolyPolygon() );
+ }
+ break;
+
+ case META_FLOATTRANSPARENT_ACTION:
+ {
+ const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pMA;
+
+ 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;
+
+ aSrcLineInfo = LineInfo();
+ SetAllAttr();
+
+ 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 );
+
+ WriteRecords( aTmpMtf );
+ }
+ break;
+
+ case( META_LAYOUTMODE_ACTION ):
+ {
+ sal_uInt32 nLayoutMode = ( (MetaLayoutModeAction*) pMA )->GetLayoutMode();
+ eSrcHorTextAlign = 0; // TA_LEFT
+ if (nLayoutMode & TEXT_LAYOUT_BIDI_RTL)
+ {
+ eSrcHorTextAlign = W_TA_RIGHT | W_TA_RTLREADING;
+ }
+ if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_RIGHT)
+ eSrcHorTextAlign |= W_TA_RIGHT;
+ else if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT)
+ eSrcHorTextAlign &= ~W_TA_RIGHT;
+ break;
+ }
+
+ // Unsupported Actions
+ case META_MASK_ACTION:
+ case META_MASKSCALE_ACTION:
+ case META_MASKSCALEPART_ACTION:
+ {
+ OSL_FAIL( "Unsupported action: MetaMask...Action!" );
+ }
+ break;
+
+ case META_CLIPREGION_ACTION:
+ break;
+
+ case META_ISECTREGIONCLIPREGION_ACTION:
+ {
+ OSL_FAIL( "Unsupported action: MetaISectRegionClipRegionAction!" );
+ }
+ break;
+
+ case META_MOVECLIPREGION_ACTION:
+ {
+ OSL_FAIL( "Unsupported action: MetaMoveClipRegionAction!" );
+ }
+ break;
+
+ default:
+ {
+ OSL_FAIL( "Unsupported meta action!" );
+ }
+ break;
+ }
+
+ nWrittenActions++;
+ MayCallback();
+
+ if (pWMF->GetError())
+ bStatus=sal_False;
+
+ if(bStatus==sal_False)
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void WMFWriter::WriteHeader( const GDIMetaFile &, sal_Bool bPlaceable )
+{
+ if( bPlaceable )
+ {
+ sal_uInt16 nCheckSum, nValue;
+ Size aSize( pVirDev->LogicToLogic(Size(1,1),MapMode(MAP_INCH), aTargetMapMode) );
+ sal_uInt16 nUnitsPerInch = (sal_uInt16) ( ( aSize.Width() + aSize.Height() ) >> 1 );
+
+ nCheckSum=0;
+ nValue=0xcdd7; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x9ac6; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=(sal_uInt16) aTargetSize.Width(); nCheckSum^=nValue; *pWMF << nValue;
+ nValue=(sal_uInt16) aTargetSize.Height(); nCheckSum^=nValue; *pWMF << nValue;
+ nValue=nUnitsPerInch; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
+ *pWMF << nCheckSum;
+ }
+
+ nMetafileHeaderPos=pWMF->Tell();
+ *pWMF << (sal_uInt16)0x0001 // Typ: Datei
+ << (sal_uInt16)0x0009 // Headerlaenge in Worten
+ << (sal_uInt16)0x0300 // Version als BCD-Zahl
+ << (sal_uInt32) 0x00000000 // Dateilaenge (ohne 1. Header), wird spaeter durch UpdateHeader() berichtigt
+ << (sal_uInt16)MAXOBJECTHANDLES // Maximalezahl der gleichzeitigen Objekte
+ << (sal_uInt32) 0x00000000 // Maximale Record-laenge, wird spaeter durch UpdateHeader() berichtigt
+ << (sal_uInt16)0x0000; // Reserved
+}
+
+// ------------------------------------------------------------------------
+
+void WMFWriter::UpdateHeader()
+{
+ sal_uLong nPos;
+ sal_uInt32 nFileSize;
+
+ nPos=pWMF->Tell(); // Endposition = Gesammtgroesse der Datei
+ nFileSize=nPos-nMetafileHeaderPos; // Groesse des 1. Headers abziehen
+ if ((nFileSize&1)!=0) { // ggf. auf ganze Worte aufrunden
+ *pWMF << (sal_uInt8)0;
+ nPos++;
+ nFileSize++;
+ }
+ nFileSize>>=1; // In Anzahl Worte umrechnen
+ pWMF->Seek(nMetafileHeaderPos+6); // Zum Dateigroessen-Eintrag im zweiten Header
+ *pWMF << nFileSize; // Dateigroesse berichtigen
+ pWMF->SeekRel(2); // Zum Max-Record-Laenge-Eintrag im zweiten Header
+ *pWMF << nMaxRecordSize; // und berichtigen
+ pWMF->Seek(nPos);
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool WMFWriter::WriteWMF( const GDIMetaFile& rMTF, SvStream& rTargetStream,
+ FilterConfigItem* pFConfigItem, sal_Bool bPlaceable )
+{
+ WMFWriterAttrStackMember * pAt;
+
+ bEmbedEMF = sal_True;
+ bStatus=sal_True;
+ pConvert = 0;
+ pVirDev = new VirtualDevice;
+
+ pFilterConfigItem = pFConfigItem;
+ if ( pFilterConfigItem )
+ {
+ xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
+ if ( xStatusIndicator.is() )
+ {
+ rtl::OUString aMsg;
+ xStatusIndicator->start( aMsg, 100 );
+ }
+ }
+ nLastPercent=0;
+
+ pWMF=&rTargetStream;
+ pWMF->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+
+ nMaxRecordSize=0;
+
+ aSrcMapMode=rMTF.GetPrefMapMode();
+
+ if( bPlaceable )
+ {
+ aTargetMapMode = aSrcMapMode;
+ aTargetSize = rMTF.GetPrefSize();
+ nTargetDivisor = CalcSaveTargetMapMode(aTargetMapMode, aTargetSize);
+ aTargetSize.Width() /= nTargetDivisor;
+ aTargetSize.Height() /= nTargetDivisor;
+ }
+ else
+ {
+ aTargetMapMode = MapMode( MAP_INCH );
+
+ const long nUnit = pVirDev->LogicToPixel( Size( 1, 1 ), aTargetMapMode ).Width();
+ const Fraction aFrac( 1, nUnit );
+
+ aTargetMapMode.SetScaleX( aFrac );
+ aTargetMapMode.SetScaleY( aFrac );
+ aTargetSize = pVirDev->LogicToLogic( rMTF.GetPrefSize(), aSrcMapMode, aTargetMapMode );
+ }
+
+ pVirDev->SetMapMode( aTargetMapMode );
+
+ pAttrStack=NULL;
+
+ for (sal_uInt16 i=0; i<MAXOBJECTHANDLES; i++)
+ bHandleAllocated[i]=sal_False;
+
+ nDstPenHandle=0xffff;
+ nDstFontHandle=0xffff;
+ nDstBrushHandle=0xffff;
+
+ nNumberOfActions=0;
+ nNumberOfBitmaps=0;
+ nWrittenActions=0;
+ nWrittenBitmaps=0;
+ nActBitmapPercent=0;
+
+ CountActionsAndBitmaps(rMTF);
+
+ WriteHeader(rMTF,bPlaceable);
+ if( bEmbedEMF )
+ WriteEmbeddedEMF( rMTF );
+ WMFRecord_SetWindowOrg(Point(0,0));
+ WMFRecord_SetWindowExt(rMTF.GetPrefSize());
+ WMFRecord_SetBkMode( sal_True );
+
+ eDstROP2 = eSrcRasterOp = ROP_OVERPAINT;
+ WMFRecord_SetROP2(eDstROP2);
+
+ aDstLineInfo = LineInfo();
+ aDstLineColor = aSrcLineColor = Color( COL_BLACK );
+ CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
+
+ aDstFillColor = aSrcFillColor = Color( COL_WHITE );
+ CreateSelectDeleteBrush( aDstFillColor );
+
+ aDstClipRegion = aSrcClipRegion = Region();
+ bDstIsClipping = bSrcIsClipping = sal_False;
+
+ Font aFont;
+ aFont.SetCharSet( GetExtendedTextEncoding( RTL_TEXTENCODING_MS_1252 ) );
+ aFont.SetColor( Color( COL_WHITE ) );
+ aFont.SetAlign( ALIGN_BASELINE );
+ aDstFont = aSrcFont = aFont;
+ CreateSelectDeleteFont(aDstFont);
+
+ eDstTextAlign = eSrcTextAlign = ALIGN_BASELINE;
+ eDstHorTextAlign = eSrcHorTextAlign = W_TA_LEFT;
+ WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
+
+ aDstTextColor = aSrcTextColor = Color( COL_WHITE );
+ WMFRecord_SetTextColor(aDstTextColor);
+
+ // Write records
+ WriteRecords(rMTF);
+
+ WMFRecord_EndOfFile();
+ UpdateHeader();
+
+ while(pAttrStack)
+ {
+ pAt=pAttrStack;
+ pAttrStack=pAt->pSucc;
+ delete pAt;
+ }
+
+ delete pVirDev;
+ delete pConvert;
+
+ if ( xStatusIndicator.is() )
+ xStatusIndicator->end();
+
+ return bStatus;
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 WMFWriter::CalcSaveTargetMapMode(MapMode& rMapMode,
+ const Size& rPrefSize)
+{
+ Fraction aDivFrac(2, 1);
+ sal_uInt16 nDivisor = 1;
+
+ Size aSize = pVirDev->LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
+
+ while( nDivisor <= 64 && (aSize.Width() > 32767 || aSize.Height() > 32767) )
+ {
+ Fraction aFrac = rMapMode.GetScaleX();
+
+ aFrac *= aDivFrac;
+ rMapMode.SetScaleX(aFrac);
+ aFrac = rMapMode.GetScaleY();
+ aFrac *= aDivFrac;
+ rMapMode.SetScaleY(aFrac);
+ nDivisor <<= 1;
+ aSize = pVirDev->LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
+ }
+
+ return nDivisor;
+}
+
+// ------------------------------------------------------------------------
+
+void WMFWriter::WriteEmbeddedEMF( const GDIMetaFile& rMTF )
+{
+ SvMemoryStream aStream;
+ EMFWriter aEMFWriter(aStream);
+
+ if( aEMFWriter.WriteEMF( rMTF ) )
+ {
+ sal_Size nTotalSize = aStream.Tell();
+ if( nTotalSize > SAL_MAX_UINT32 )
+ return;
+ aStream.Seek( 0 );
+ sal_uInt32 nRemainingSize = static_cast< sal_uInt32 >( nTotalSize );
+ sal_uInt32 nRecCounts = ( (nTotalSize - 1) / 0x2000 ) + 1;
+ sal_uInt16 nCheckSum = 0, nWord;
+
+ sal_uInt32 nPos = 0;
+
+ while( nPos + 1 < nTotalSize )
+ {
+ aStream >> nWord;
+ nCheckSum ^= nWord;
+ nPos += 2;
+ }
+
+ nCheckSum = static_cast< sal_uInt16 >( nCheckSum * -1 );
+
+ aStream.Seek( 0 );
+ while( nRemainingSize > 0 )
+ {
+ sal_uInt32 nCurSize;
+ if( nRemainingSize > 0x2000 )
+ {
+ nCurSize = 0x2000;
+ nRemainingSize -= 0x2000;
+ }
+ else
+ {
+ nCurSize = nRemainingSize;
+ nRemainingSize = 0;
+ }
+ WriteEMFRecord( aStream,
+ nCurSize,
+ nRemainingSize,
+ nTotalSize,
+ nRecCounts,
+ nCheckSum );
+ nCheckSum = 0;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void WMFWriter::WriteEMFRecord( SvMemoryStream& rStream, sal_uInt32 nCurSize, sal_uInt32 nRemainingSize,
+ sal_uInt32 nTotalSize, sal_uInt32 nRecCounts, sal_uInt16 nCheckSum )
+{
+ // according to http://msdn.microsoft.com/en-us/library/dd366152%28PROT.13%29.aspx
+ WriteRecordHeader( 0, W_META_ESCAPE );
+ *pWMF << (sal_uInt16)W_MFCOMMENT // same as META_ESCAPE_ENHANCED_METAFILE
+ << (sal_uInt16)( nCurSize + 34 ) // we will always have a 34 byte escape header:
+ << (sal_uInt32) 0x43464D57 // WMFC
+ << (sal_uInt32) 0x00000001 // Comment type
+ << (sal_uInt32) 0x00010000 // version
+ << nCheckSum // check sum
+ << (sal_uInt32) 0 // flags = 0
+ << nRecCounts // total number of records
+ << nCurSize // size of this record's data
+ << nRemainingSize // remaining size of data in following records, missing in MSDN documentation
+ << nTotalSize; // total size of EMF stream
+
+ pWMF->Write( static_cast< const sal_Char* >( rStream.GetData() ) + rStream.Tell(), nCurSize );
+ rStream.SeekRel( nCurSize );
+ UpdateRecordHeader();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/wmfwr.hxx b/vcl/source/filter/wmf/wmfwr.hxx
new file mode 100644
index 000000000000..f71abaa8ea93
--- /dev/null
+++ b/vcl/source/filter/wmf/wmfwr.hxx
@@ -0,0 +1,220 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#ifndef _WMFWR_HXX
+#define _WMFWR_HXX
+
+#include <vcl/metaact.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/virdev.hxx>
+#include <svtools/fltcall.hxx>
+
+// -----------------------------------------------------------------------------
+
+#define MAXOBJECTHANDLES 16
+
+// -----------------------------------------------------------------------------
+
+struct WMFWriterAttrStackMember
+{
+ struct WMFWriterAttrStackMember * pSucc;
+ Color aLineColor;
+ Color aFillColor;
+ Color aTextColor;
+ LineInfo aLineInfo;
+ TextAlign eTextAlign;
+ RasterOp eRasterOp;
+ Font aFont;
+ MapMode aMapMode;
+ Region aClipRegion;
+ sal_uInt16 nFlags;
+};
+
+// -------------
+// - WMFWriter -
+// -------------
+
+class StarSymbolToMSMultiFont;
+class LineInfo;
+namespace basegfx { class B2DPolygon; }
+
+class WMFWriter
+{
+private:
+
+ sal_Bool bStatus;
+
+ sal_uLong nLastPercent; // Mit welcher Zahl pCallback zuletzt aufgerufen wurde.
+ FilterConfigItem* pFilterConfigItem;
+
+ com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
+
+ SvStream* pWMF;
+ VirtualDevice* pVirDev;
+ StarSymbolToMSMultiFont *pConvert;
+ MapMode aTargetMapMode;
+ Size aTargetSize;
+ sal_uInt16 nTargetDivisor;
+
+ sal_uLong nMetafileHeaderPos;
+ sal_uInt32 nMaxRecordSize; // in Worten
+ sal_uLong nActRecordPos;
+
+ // Aktuelle Attribute im Quell-Metafile:
+ Color aSrcLineColor;
+ Color aSrcFillColor;
+ Color aSrcTextColor;
+ LineInfo aSrcLineInfo;
+ RasterOp eSrcRasterOp;
+ FontAlign eSrcTextAlign;
+ Font aSrcFont;
+ MapMode aSrcMapMode;
+ sal_Bool bSrcIsClipping;
+ Region aSrcClipRegion;
+ WMFWriterAttrStackMember * pAttrStack;
+
+ sal_uInt32 eSrcHorTextAlign;
+
+ // Aktuelle Attribute im Ziel-Metafile:
+ Color aDstLineColor;
+ Color aDstFillColor;
+ Color aDstTextColor;
+ LineInfo aDstLineInfo;
+ RasterOp eDstROP2;
+ FontAlign eDstTextAlign;
+ Font aDstFont;
+
+ sal_uInt32 eDstHorTextAlign;
+
+ sal_Bool bDstIsClipping; // ???: derzeit unberuecksichtigt
+ Region aDstClipRegion; // ???: derzeit unberuecksichtigt
+ sal_Bool bHandleAllocated[MAXOBJECTHANDLES]; // Welche Handles vergeben sind
+ sal_uInt16 nDstPenHandle,nDstFontHandle,nDstBrushHandle; // Welche Handles die jeweiligen
+ // Selected-Objects besitzen
+ // 0xffff = keines:
+
+ // Damit nicht bei jeder Operation alle Attribute verglichen werden muessen:
+
+ sal_uLong nNumberOfActions; // Anzahl der Actions im GDIMetafile
+ sal_uLong nNumberOfBitmaps; // Anzahl der Bitmaps
+ sal_uLong nWrittenActions; // Anzahl der bereits verarbeiteten Actions beim Schreiben der Orders
+ sal_uLong nWrittenBitmaps; // Anzahl der bereits geschriebenen Bitmaps
+ sal_uLong nActBitmapPercent; // Wieviel Prozent die naechste Bitmap schon geschrieben ist.
+
+ sal_Bool bEmbedEMF; // optionally embedd EMF data into WMF
+
+ void MayCallback();
+ // Berechnet anhand der obigen 5 Parameter eine Prozentzahl
+ // und macht dann ggf. einen Callback. Setzt bStatus auf FALSE wenn User abbrechen
+ // moechte.
+
+ void CountActionsAndBitmaps(const GDIMetaFile & rMTF);
+ // Zaehlt die Bitmaps und Actions (nNumberOfActions und nNumberOfBitmaps muessen
+ // zu Anfang auf 0 gesetzt werden, weil diese Methode rekursiv ist)
+
+ void WritePointXY(const Point & rPoint);
+ void WritePointYX(const Point & rPoint);
+ sal_Int32 ScaleWidth( sal_Int32 nDX );
+ void WriteSize(const Size & rSize);
+ void WriteHeightWidth(const Size & rSize);
+ void WriteRectangle(const Rectangle & rRect);
+ void WriteColor(const Color & rColor);
+
+ void WriteRecordHeader(sal_uInt32 nSizeWords, sal_uInt16 nType);
+ // nSizeWords ist die Groesse des gesammten Records in Anzahl Worte.
+ // Wenn nSizeWords unbekannt ist, dann 0 einsetzen (siehe UpdateRecordHeader()).
+
+ void UpdateRecordHeader();
+ // berichtig die Groesse des Records nach dem Schreiben der Parameter, wenn
+ // nSizeWords bei Aufruf von WriteRecordHeader(..) unbekannt war.
+ // fuegt ggf. noch ein BYTE 0 ein damit Anzahl Bytes immer gerade.
+
+ void WMFRecord_Arc(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt);
+ void WMFRecord_Chord(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt);
+ void WMFRecord_CreateBrushIndirect(const Color& rColor);
+ void WMFRecord_CreateFontIndirect(const Font & rFont);
+ void WMFRecord_CreatePenIndirect(const Color& rColor, const LineInfo& rLineInfo );
+ void WMFRecord_DeleteObject(sal_uInt16 nObjectHandle);
+ void WMFRecord_Ellipse(const Rectangle & rRect);
+ void WMFRecord_Escape( sal_uInt32 nEsc, sal_uInt32 nLen, const sal_Int8* pData );
+ sal_Bool WMFRecord_Escape_Unicode( const Point& rPoint, const String& rStr, const sal_Int32 * pDXAry );
+ void WMFRecord_ExtTextOut(const Point & rPoint, const String & rString, const sal_Int32 * pDXAry);
+
+ void TrueExtTextOut(const Point & rPoint, const String & rString,
+ const rtl::OString& rByteString, const sal_Int32 * pDXAry);
+ void TrueTextOut(const Point & rPoint, const rtl::OString& rString);
+ void WMFRecord_LineTo(const Point & rPoint);
+ void WMFRecord_MoveTo(const Point & rPoint);
+ void WMFRecord_Pie(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt);
+ void WMFRecord_Polygon(const Polygon & rPoly);
+ void WMFRecord_PolyLine(const Polygon & rPoly);
+ void WMFRecord_PolyPolygon(const PolyPolygon & rPolyPoly);
+ void WMFRecord_Rectangle(const Rectangle & rRect);
+ void WMFRecord_RestoreDC();
+ void WMFRecord_RoundRect(const Rectangle & rRect, long nHorzRound, long nVertRound);
+ void WMFRecord_SaveDC();
+ void WMFRecord_SelectObject(sal_uInt16 nObjectHandle);
+ void WMFRecord_SetBkMode(sal_Bool bTransparent);
+ void WMFRecord_SetStretchBltMode();
+ void WMFRecord_SetPixel(const Point & rPoint, const Color & rColor);
+ void WMFRecord_SetROP2(RasterOp eROP);
+ void WMFRecord_SetTextAlign(FontAlign eFontAlign, sal_uInt32 eHorTextAlign);
+ void WMFRecord_SetTextColor(const Color & rColor);
+ void WMFRecord_SetWindowExt(const Size & rSize);
+ void WMFRecord_SetWindowOrg(const Point & rPoint);
+ void WMFRecord_StretchDIB(const Point & rPoint, const Size & rSize, const Bitmap & rBitmap, sal_uInt32 nROP = 0UL );
+ void WMFRecord_TextOut(const Point & rPoint, const String & rString);
+ void WMFRecord_EndOfFile();
+ void WMFRecord_IntersectClipRect( const Rectangle& rRect);
+
+ sal_uInt16 AllocHandle();
+ void FreeHandle(sal_uInt16 nObjectHandle);
+ void CreateSelectDeletePen( const Color& rColor, const LineInfo& rLineInfo );
+ void CreateSelectDeleteFont(const Font & rFont);
+ void CreateSelectDeleteBrush(const Color& rColor);
+
+ void SetLineAndFillAttr();
+ void SetAllAttr();
+
+ void HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon);
+ void WriteRecords(const GDIMetaFile & rMTF);
+
+ void WriteHeader(const GDIMetaFile & rMTF, sal_Bool bPlaceable);
+ void UpdateHeader();
+
+ void WriteEmbeddedEMF( const GDIMetaFile& rMTF );
+ void WriteEMFRecord( SvMemoryStream& rStream, sal_uInt32 nCurSize,
+ sal_uInt32 nRemainingSize,
+ sal_uInt32 nTotalSize,
+ sal_uInt32 nRecCounts,
+ sal_uInt16 nCheckSum );
+
+ sal_uInt16 CalcSaveTargetMapMode(MapMode& rMapMode, const Size& rPrefSize);
+
+public:
+
+ WMFWriter() {}
+
+ sal_Bool WriteWMF(const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pFilterConfigItem, sal_Bool bPlaceable=sal_True);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */