From f1fee2a65c8c1968798e1246a4b455d9160d8eb9 Mon Sep 17 00:00:00 2001 From: Muthu Subramanian Date: Thu, 6 Dec 2012 12:21:24 +0530 Subject: n#780748: Basic EMF+ implementation. * Minimalistic implementation of EMF+ export * Currently exports transparent polygons. --- svtools/source/filter/wmf/emfwr.cxx | 204 +++++++++++++++++++++++++++++++++++- svtools/source/filter/wmf/emfwr.hxx | 12 +++ 2 files changed, 215 insertions(+), 1 deletion(-) (limited to 'svtools') diff --git a/svtools/source/filter/wmf/emfwr.cxx b/svtools/source/filter/wmf/emfwr.cxx index c4caf024b47f..39e33c078909 100644 --- a/svtools/source/filter/wmf/emfwr.cxx +++ b/svtools/source/filter/wmf/emfwr.cxx @@ -130,6 +130,9 @@ #define WIN_SRCPAINT 0x00EE0086L #define WIN_SRCAND 0x008800C6L #define WIN_SRCINVERT 0x00660046L +#define WIN_EMR_COMMENT_EMFSPOOL 0x00000000L +#define WIN_EMR_COMMENT_EMFPLUS 0x2B464D45L +#define WIN_EMR_COMMENT_PUBLIC 0x43494447L #define HANDLE_INVALID 0xffffffff #define MAXHANDLES 65000 @@ -154,10 +157,194 @@ #define MM_ANISOTROPIC 8 +typedef enum +{ + EmfPlusHeader = 0x4001, + EmfPlusEndOfFile = 0x4002, + EmfPlusComment = 0x4003, + EmfPlusGetDC = 0x4004, + EmfPlusMultiFormatStart = 0x4005, + EmfPlusMultiFormatSection = 0x4006, + EmfPlusMultiFormatEnd = 0x4007, + EmfPlusObject = 0x4008, + EmfPlusClear = 0x4009, + EmfPlusFillRects = 0x400A, + EmfPlusDrawRects = 0x400B, + EmfPlusFillPolygon = 0x400C, + EmfPlusDrawLines = 0x400D, + EmfPlusFillEllipse = 0x400E, + EmfPlusDrawEllipse = 0x400F, + EmfPlusFillPie = 0x4010, + EmfPlusDrawPie = 0x4011, + EmfPlusDrawArc = 0x4012, + EmfPlusFillRegion = 0x4013, + EmfPlusFillPath = 0x4014, + EmfPlusDrawPath = 0x4015, + EmfPlusFillClosedCurve = 0x4016, + EmfPlusDrawClosedCurve = 0x4017, + EmfPlusDrawCurve = 0x4018, + EmfPlusDrawBeziers = 0x4019, + EmfPlusDrawImage = 0x401A, + EmfPlusDrawImagePoints = 0x401B, + EmfPlusDrawstring = 0x401C, + EmfPlusSetRenderingOrigin = 0x401D, + EmfPlusSetAntiAliasMode = 0x401E, + EmfPlusSetTextRenderingHint = 0x401F, + EmfPlusSetTextContrast = 0x4020, + EmfPlusSetInterpolationMode = 0x4021, + EmfPlusSetPixelOffsetMode = 0x4022, + EmfPlusSetCompositingMode = 0x4023, + EmfPlusSetCompositingQuality = 0x4024, + EmfPlusSave = 0x4025, + EmfPlusRestore = 0x4026, + EmfPlusBeginContainer = 0x4027, + EmfPlusBeginContainerNoParams = 0x4028, + EmfPlusEndContainer = 0x4029, + EmfPlusSetWorldTransform = 0x402A, + EmfPlusResetWorldTransform = 0x402B, + EmfPlusMultiplyWorldTransform = 0x402C, + EmfPlusTranslateWorldTransform = 0x402D, + EmfPlusScaleWorldTransform = 0x402E, + EmfPlusRotateWorldTransform = 0x402F, + EmfPlusSetPageTransform = 0x4030, + EmfPlusResetClip = 0x4031, + EmfPlusSetClipRect = 0x4032, + EmfPlusSetClipPath = 0x4033, + EmfPlusSetClipRegion = 0x4034, + EmfPlusOffsetClip = 0x4035, + EmfPlusDrawDriverstring = 0x4036, + EmfPlusStrokeFillPath = 0x4037, + EmfPlusSerializableObject = 0x4038, + EmfPlusSetTSGraphics = 0x4039, + EmfPlusSetTSClip = 0x403A +} EmfPlusRecordType; + + // ------------- // - EMFWriter - // ------------- +void EMFWriter::ImplBeginCommentRecord( sal_Int32 nCommentType ) +{ + ImplBeginRecord( WIN_EMR_GDICOMMENT ); + m_rStm.SeekRel( 4 ); + m_rStm<< (sal_Int32) nCommentType; +} + +void EMFWriter::ImplEndCommentRecord() +{ + if( mbRecordOpen ) + { + sal_Int32 nActPos = m_rStm.Tell(); + m_rStm.Seek( mnRecordPos + 8 ); + m_rStm << (sal_uInt32)( nActPos - mnRecordPos - 0xc ); + m_rStm.Seek( nActPos ); + } + ImplEndRecord(); +} + +void EMFWriter::ImplBeginPlusRecord( sal_uInt16 nType, sal_uInt16 nFlags ) +{ + DBG_ASSERT( !mbRecordPlusOpen, "Another EMF+ record is already opened!" ); + + if( !mbRecordPlusOpen ) + { + mbRecordPlusOpen = sal_True; + mnRecordPlusPos = m_rStm.Tell(); + + m_rStm << (sal_uInt16) nType << (sal_uInt16) nFlags; + m_rStm.SeekRel( 8 ); + } +} + +// ----------------------------------------------------------------------------- + +void EMFWriter::ImplEndPlusRecord() +{ + DBG_ASSERT( mbRecordPlusOpen, "EMF+ Record was not opened!" ); + + if( mbRecordPlusOpen ) + { + sal_Int32 nActPos = m_rStm.Tell(); + sal_Int32 nSize = nActPos - mnRecordPlusPos; + m_rStm.Seek( mnRecordPlusPos + 4 ); + m_rStm << (sal_uInt32)( nSize ) // Size + << (sal_uInt32) ( nSize - 0xc ); // Data Size + m_rStm.Seek( nActPos ); + mbRecordPlusOpen = sal_False; + } +} + +void EMFWriter::ImplPlusRecord( sal_uInt16 nType, sal_uInt16 nFlags ) +{ + ImplBeginPlusRecord( nType, nFlags ); + ImplEndPlusRecord(); +} + +void EMFWriter::WriteEMFPlusHeader( const Size &rMtfSizePix, const Size &rMtfSizeLog ) +{ + ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS ); + m_rStm<< (sal_Int16) EmfPlusHeader; + m_rStm<< (sal_Int16) 0x01 // Flags - Dual Mode // TODO: Check this + << (sal_Int32) 0x1C // Size + << (sal_Int32) 0x10 // Data Size + << (sal_Int32) 0xdbc01002 // (lower 12bits) 1-> v1 2-> v1.1 // TODO: Check this + << (sal_Int32) 0x01 // Video display + << (sal_Int32) ( rMtfSizePix.Width()*25 / (rMtfSizeLog.Width()/100) ) // DPI X + << (sal_Int32) ( rMtfSizePix.Height()*25 / (rMtfSizeLog.Height()/100) ); // DPI Y + ImplEndCommentRecord(); + + // Write more properties + ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS ); + ImplPlusRecord( EmfPlusSetPixelOffsetMode, 0x0 ); + ImplPlusRecord( EmfPlusSetAntiAliasMode, 0x09 ); // TODO: Check actual values for AntiAlias + ImplPlusRecord( EmfPlusSetCompositingQuality, 0x0100 ); // Default Quality + ImplPlusRecord( EmfPlusSetPageTransform, 1 ); + ImplPlusRecord( EmfPlusSetInterpolationMode, 0x00 ); // Default + ImplPlusRecord( EmfPlusGetDC, 0x00 ); + ImplEndCommentRecord(); +} + +void EMFWriter::ImplWritePlusEOF() +{ + ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS ); + ImplPlusRecord( EmfPlusEndOfFile, 0x0 ); + ImplEndCommentRecord(); +} + +void EMFWriter::ImplWritePlusColor( const Color& rColor, const sal_uInt32& nTrans ) +{ + sal_uInt32 nAlpha = ((100-nTrans)*0xFF)/100; + sal_uInt32 nCol = rColor.GetBlue(); + + nCol |= ( (sal_uInt32) rColor.GetGreen() ) << 8; + nCol |= ( (sal_uInt32) rColor.GetRed() ) << 16; + nCol |= ( nAlpha << 24 ); + m_rStm << nCol; +} + +void EMFWriter::ImplWritePlusPoint( const Point& rPoint ) +{ + // Convert to pixels + const Point aPoint(maVDev.LogicToPixel( rPoint, maDestMapMode )); + m_rStm << (sal_uInt16) aPoint.X() << (sal_uInt16) aPoint.Y(); +} + +void EMFWriter::ImplWritePlusFillPolygonRecord( const Polygon& rPoly, const sal_uInt32& nTrans ) +{ + ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS ); + if( rPoly.GetSize() ) + { + ImplBeginPlusRecord( EmfPlusFillPolygon, 0xC000 ); // Sets the color as well + ImplWritePlusColor( maVDev.GetFillColor(), nTrans ); + m_rStm << (sal_uInt32) rPoly.GetSize(); + for( sal_uInt16 i = 0; i < rPoly.GetSize(); i++ ) + ImplWritePlusPoint( rPoly[ i ] ); + ImplEndPlusRecord(); + } + ImplEndCommentRecord(); +} + sal_Bool EMFWriter::WriteEMF( const GDIMetaFile& rMtf, FilterConfigItem* pFilterConfigItem ) { const sal_uLong nHeaderPos = m_rStm.Tell(); @@ -165,8 +352,11 @@ sal_Bool EMFWriter::WriteEMF( const GDIMetaFile& rMtf, FilterConfigItem* pFilter mpHandlesUsed = new sal_Bool[ MAXHANDLES ]; memset( mpHandlesUsed, 0, MAXHANDLES * sizeof( sal_Bool ) ); mnHorTextAlign = mnHandleCount = mnLastPercent = mnRecordPos = mnRecordCount = 0; + mnRecordPlusPos = 0; mnLineHandle = mnFillHandle = mnTextHandle = HANDLE_INVALID; mbRecordOpen = sal_False; + mbRecordPlusOpen = false; + maVDev.EnableOutput( sal_False ); maVDev.SetMapMode( rMtf.GetPrefMapMode() ); @@ -182,6 +372,9 @@ sal_Bool EMFWriter::WriteEMF( const GDIMetaFile& rMtf, FilterConfigItem* pFilter // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits() m_rStm.SeekRel( 108 ); + // Write EMF+ Header + WriteEMFPlusHeader( aMtfSizePix, aMtfSizeLog ); + // write initial values // set 100th mm map mode in EMF @@ -214,6 +407,8 @@ sal_Bool EMFWriter::WriteEMF( const GDIMetaFile& rMtf, FilterConfigItem* pFilter // write emf data ImplWrite( rMtf ); + ImplWritePlusEOF(); + ImplBeginRecord( WIN_EMR_EOF ); m_rStm<< (sal_uInt32)0 // nPalEntries << (sal_uInt32)0x10 // offPalEntries @@ -1107,9 +1302,16 @@ void EMFWriter::ImplWrite( const GDIMetaFile& rMtf ) case META_TRANSPARENT_ACTION: { + const PolyPolygon& rPolyPoly = ( (MetaTransparentAction*) pAction )->GetPolyPolygon(); + if( rPolyPoly.Count() ) + ImplWritePlusFillPolygonRecord( rPolyPoly[0], ( (MetaTransparentAction*)pAction)->GetTransparence() ); ImplCheckFillAttr(); ImplCheckLineAttr(); - ImplWritePolyPolygonRecord( ( (MetaTransparentAction*) pAction )->GetPolyPolygon() ); + ImplWritePolyPolygonRecord( rPolyPoly ); + + ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS ); + ImplPlusRecord( EmfPlusGetDC, 0x00 ); + ImplEndCommentRecord(); } break; diff --git a/svtools/source/filter/wmf/emfwr.hxx b/svtools/source/filter/wmf/emfwr.hxx index f930c352ae33..3e22e0385f17 100644 --- a/svtools/source/filter/wmf/emfwr.hxx +++ b/svtools/source/filter/wmf/emfwr.hxx @@ -46,7 +46,9 @@ private: sal_uLong mnLastPercent; sal_uLong mnRecordCount; sal_uLong mnRecordPos; + sal_uLong mnRecordPlusPos; sal_Bool mbRecordOpen; + sal_Bool mbRecordPlusOpen; sal_Bool mbLineChanged; sal_uInt32 mnLineHandle; sal_Bool mbFillChanged; @@ -57,6 +59,11 @@ private: void ImplBeginRecord( sal_uInt32 nType ); void ImplEndRecord(); + void ImplBeginPlusRecord( sal_uInt16 nType, sal_uInt16 nFlags ); + void ImplEndPlusRecord(); + void ImplPlusRecord( sal_uInt16 nType, sal_uInt16 nFlags ); + void ImplBeginCommentRecord( sal_Int32 nCommentType ); + void ImplEndCommentRecord(); sal_uLong ImplAcquireHandle(); void ImplReleaseHandle( sal_uLong nHandle ); @@ -80,6 +87,11 @@ private: void Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon); void ImplWrite( const GDIMetaFile& rMtf ); + void WriteEMFPlusHeader( const Size &rMtfSizePix, const Size &rMtfSizeLog ); + void ImplWritePlusEOF(); + void ImplWritePlusFillPolygonRecord( const Polygon& rPoly, const sal_uInt32& nTrans ); + void ImplWritePlusColor( const Color& rColor, const sal_uInt32& nTrans ); + void ImplWritePlusPoint( const Point& rPoint ); public: -- cgit