diff options
Diffstat (limited to 'svtools/source/filter/wmf/enhwmf.cxx')
-rw-r--r-- | svtools/source/filter/wmf/enhwmf.cxx | 199 |
1 files changed, 195 insertions, 4 deletions
diff --git a/svtools/source/filter/wmf/enhwmf.cxx b/svtools/source/filter/wmf/enhwmf.cxx index ec7fec9fdb1e..23990473aa60 100644 --- a/svtools/source/filter/wmf/enhwmf.cxx +++ b/svtools/source/filter/wmf/enhwmf.cxx @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -158,6 +159,8 @@ #define EMR_SETLINKEDUFIS 119 #define EMR_SETTEXTJUSTIFICATION 120 +#define EMFP_DEBUG(x) +//#define EMFP_DEBUG(x) x //----------------------------------------------------------------------------------- @@ -176,7 +179,7 @@ SvStream& operator>>( SvStream& rIn, XForm& rXForm ) { if ( sizeof( float ) != 4 ) { - DBG_ERROR( "EnhWMFReader::sizeof( float ) != 4" ); + OSL_FAIL( "EnhWMFReader::sizeof( float ) != 4" ); rXForm = XForm(); } else @@ -229,6 +232,106 @@ static sal_Bool ImplReadRegion( PolyPolygon& rPolyPoly, SvStream& rSt, sal_uInt3 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( UniString::CreateFromAscii( "/tmp/emf-stream.emf" ), STREAM_WRITE | STREAM_TRUNC ); + + *pWMF >> file; + file.Flush(); + file.Close(); + + pWMF->Seek( pos );) + } + bEMFPlus = true; + + void *buffer = malloc( length ); + + int pos = pWMF->Tell(); + pOut->PassEMFPlus( buffer, pWMF->Read( buffer, length ) ); + pWMF->Seek( pos ); + + bHaveDC = false; + + length -= 4; + + while (length > 0) { + sal_uInt16 type, flags; + sal_uInt32 size, dataSize; + sal_uInt32 next; + + *pWMF >> type >> flags >> size >> dataSize; + + 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", type)); + } + + next = pWMF->Tell() + ( size - 12 ); + + length -= size; + + pWMF->Seek( next ); + } + + free( buffer ); +} + +void EnhWMFReader::ReadGDIComment() +{ + sal_uInt32 type; + + *pWMF >> type; + + switch( type ) { + case 2: { + sal_Int32 x, y, r, b; + + EMFP_DEBUG(printf ("\t\tBEGINGROUP\n")); + + *pWMF >> x >> y >> r >> b; + EMFP_DEBUG(printf ("\t\tbounding rectangle: %d,%d x %d,%d\n", x, y, r, b)); + + sal_uInt32 l; + + *pWMF >> l; + EMFP_DEBUG(printf ("\t\tdescription length: %d\n", l)); + + break; + } + case 3: { + EMFP_DEBUG(printf ("\t\tENDGROUP\n")); + break; + } + case 0x40000004: { + EMFP_DEBUG(printf ("\t\tMULTIFORMATS\n")); + break; + } + default: + EMFP_DEBUG(printf ("\t\tunknown GDIComment\n")); + EMFP_DEBUG(dumpWords (*pWMF, 16)); + } +} + sal_Bool EnhWMFReader::ReadEnhWMF() { sal_uInt32 nStretchBltMode = 0; @@ -239,6 +342,14 @@ sal_Bool EnhWMFReader::ReadEnhWMF() sal_Int16 nX16, nY16; sal_Bool bFlag, bStatus = ReadHeader(); + sal_Bool bHaveDC = false; + +#ifdef UNX + static sal_Bool bEnableEMFPlus = ( getenv( "EMF_PLUS_DISABLE" ) == NULL ); +#else + // TODO: make it possible to disable emf+ on windows + static sal_Bool bEnableEMFPlus = sal_False; +#endif while( bStatus && nRecordCount-- ) { @@ -263,6 +374,34 @@ sal_Bool EnhWMFReader::ReadEnhWMF() bFlag = sal_False; + EMFP_DEBUG(printf ("0x%04x-0x%04x record type: %d size: %d\n", nNextPos - nRecSize, nNextPos, nRecType, nRecSize)); + + if( bEnableEMFPlus && nRecType == EMR_GDICOMMENT ) { + sal_uInt32 length; + + *pWMF >> length; + + EMFP_DEBUG(printf ("\tGDI comment\n\t\tlength: %d\n", length)); + + if( 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), id)); + + // EMF+ comment (fixme: BE?) + if( id == 0x2B464D45 && nRecSize >= 12 ) + ReadEMFPlusComment( length, bHaveDC ); + // GDIC comment, doesn't do anything useful yet => enabled only for debug + else if( id == 0x43494447 && nRecSize >= 12 ) { + EMFP_DEBUG(ReadGDIComment()); + } else { + EMFP_DEBUG(printf ("\t\tunknown id: 0x%x\n", id)); + } + } + } else if( !bEMFPlus || bHaveDC || nRecType == EMR_EOF ) + switch( nRecType ) { case EMR_POLYBEZIERTO : @@ -867,7 +1006,10 @@ sal_Bool EnhWMFReader::ReadEnhWMF() Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) ); aBitmap.Crop( aCropRect ); } - aBmpSaveList.Insert( new BSaveStruct( aBitmap, aRect, dwRop ), LIST_APPEND ); + /* Pseudocomment to add more context so that make patch.unapply + * works better. Ha! + */ + aBmpSaveList.Insert( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ), LIST_APPEND ); } } } @@ -921,7 +1063,8 @@ sal_Bool EnhWMFReader::ReadEnhWMF() Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) ); aBitmap.Crop( aCropRect ); } - aBmpSaveList.Insert( new BSaveStruct( aBitmap, aRect, dwRop ), LIST_APPEND ); + /* Another pseudocomment to make make patch.unapply work better */ + aBmpSaveList.Insert( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ), LIST_APPEND ); } } } @@ -1192,6 +1335,53 @@ sal_Bool EnhWMFReader::ReadEnhWMF() } 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; @@ -1211,7 +1401,6 @@ sal_Bool EnhWMFReader::ReadEnhWMF() case EMR_ANGLEARC : WinMtfAssertHandler( "AngleArc" ); break; case EMR_SETCOLORADJUSTMENT : WinMtfAssertHandler( "SetColorAdjustment" ); break; case EMR_POLYDRAW16 : WinMtfAssertHandler( "PolyDraw16" ); break; - case EMR_CREATEDIBPATTERNBRUSHPT : WinMtfAssertHandler( "CreateDibPatternBrushPt" ); break; case EMR_POLYTEXTOUTA : WinMtfAssertHandler( "PolyTextOutA" ); break; case EMR_POLYTEXTOUTW : WinMtfAssertHandler( "PolyTextOutW" ); break; case EMR_CREATECOLORSPACE : WinMtfAssertHandler( "CreateColorSpace" ); break; @@ -1340,3 +1529,5 @@ EnhWMFReader::~EnhWMFReader() { }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |