summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMuthu Subramanian <sumuthu@suse.com>2012-12-06 12:21:24 +0530
committerFridrich Strba <fridrich@documentfoundation.org>2013-02-25 16:32:56 +0000
commit32bc874ded4f9108a32bd76a53ecc001e6ba2a83 (patch)
treead268ad2d30dc98d25c501c607cd69e5ed1a205d
parent4536979e19d6a9a913f677225a122c13a51da1fa (diff)
n#780748: Basic EMF+ implementation.
* Minimalistic implementation of EMF+ export * Currently exports transparent polygons. (cherry picked from commit f1fee2a65c8c1968798e1246a4b455d9160d8eb9) Change-Id: I0c24c29b77c50f898fe1b8ce1904179292a1bb72 Reviewed-on: https://gerrit.libreoffice.org/2395 Reviewed-by: Fridrich Strba <fridrich@documentfoundation.org> Tested-by: Fridrich Strba <fridrich@documentfoundation.org>
-rw-r--r--vcl/source/filter/wmf/emfwr.cxx204
-rw-r--r--vcl/source/filter/wmf/emfwr.hxx12
2 files changed, 215 insertions, 1 deletions
diff --git a/vcl/source/filter/wmf/emfwr.cxx b/vcl/source/filter/wmf/emfwr.cxx
index 80d45734881e..cf8a748b0a9b 100644
--- a/vcl/source/filter/wmf/emfwr.cxx
+++ b/vcl/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/vcl/source/filter/wmf/emfwr.hxx b/vcl/source/filter/wmf/emfwr.hxx
index f930c352ae33..3e22e0385f17 100644
--- a/vcl/source/filter/wmf/emfwr.hxx
+++ b/vcl/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: