From f4f4a899f0d5520a497bbd07ccfef9086c54ca1c Mon Sep 17 00:00:00 2001 From: Cédric Bosdonnat Date: Thu, 24 Nov 2011 15:05:25 +0100 Subject: RTF import: partly fixed the WMF images scaling. --- svtools/inc/svtools/filter.hxx | 6 ++-- svtools/inc/svtools/wmf.hxx | 48 ++++++++++++++++------------ svtools/source/filter/filter.cxx | 8 ++--- svtools/source/filter/wmf/winmtf.hxx | 14 +++++--- svtools/source/filter/wmf/winwmf.cxx | 62 +++++++++++++++++++----------------- svtools/source/filter/wmf/wmf.cxx | 4 +-- svtools/source/graphic/provider.cxx | 42 +++++++++++++++++++++++- 7 files changed, 118 insertions(+), 66 deletions(-) (limited to 'svtools') diff --git a/svtools/inc/svtools/filter.hxx b/svtools/inc/svtools/filter.hxx index da3a7cb036c8..7defa39b48a5 100644 --- a/svtools/inc/svtools/filter.hxx +++ b/svtools/inc/svtools/filter.hxx @@ -39,7 +39,7 @@ #include #include -struct WMF_APMFILEHEADER; +struct WMF_EXTERNALHEADER; // ----------------------- // - GraphicFilter-Types - // ----------------------- @@ -347,14 +347,14 @@ public: SvStream& rStream, sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW, sal_uInt16 * pDeterminedFormat = NULL, sal_uInt32 nImportFlags = 0, - WMF_APMFILEHEADER *pAPMHeader = NULL ); + WMF_EXTERNALHEADER *pExtHeader = NULL ); sal_uInt16 ImportGraphic( Graphic& rGraphic, const String& rPath, SvStream& rStream, sal_uInt16 nFormat, sal_uInt16 * pDeterminedFormat, sal_uInt32 nImportFlags, com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData, - WMF_APMFILEHEADER *pAPMHeader = NULL ); + WMF_EXTERNALHEADER *pExtHeader = NULL ); sal_Bool Setup( sal_uInt16 nFormat ); diff --git a/svtools/inc/svtools/wmf.hxx b/svtools/inc/svtools/wmf.hxx index a455f443e26e..986ccfb0d785 100644 --- a/svtools/inc/svtools/wmf.hxx +++ b/svtools/inc/svtools/wmf.hxx @@ -32,30 +32,36 @@ #include "svtools/svtdllapi.h" #include -struct WMF_APMFILEHEADER { - sal_uInt32 key; - sal_uInt16 hmf; - sal_uInt16 left; - sal_uInt16 top; - sal_uInt16 right; - sal_uInt16 bottom; - sal_uInt16 inch; - sal_uInt32 reserved; - sal_uInt16 checksum; +struct WMF_EXTERNALHEADER +{ + sal_uInt16 xExt; + sal_uInt16 yExt; - WMF_APMFILEHEADER() : key(0x9ac6cdd7L), - hmf(0), - left(0), - top(0), - right(0), - bottom(0), - inch(96), - reserved(0), - checksum(0) { - } + /** One of the following values: +
    +
  • MM_TEXT
  • +
  • MM_LOMETRIC
  • +
  • MM_HIMETRIC
  • +
  • MM_LOENGLISH
  • +
  • MM_HIENGLISH
  • +
  • MM_TWIPS
  • +
  • MM_ISOTROPIC
  • +
  • MM_ANISOTROPIC
  • +
+ If this value is 0, then no external mapmode has been defined, + the internal one should then be used. + */ + sal_uInt16 mapMode; + + WMF_EXTERNALHEADER() : + xExt( 0 ), + yExt( 0 ), + mapMode( 0 ) + { + } }; -sal_Bool ConvertWMFToGDIMetaFile( SvStream & rStreamWMF, GDIMetaFile & rGDIMetaFile, FilterConfigItem* pConfigItem = NULL, WMF_APMFILEHEADER *pAPMHeader = NULL ); +sal_Bool ConvertWMFToGDIMetaFile( SvStream & rStreamWMF, GDIMetaFile & rGDIMetaFile, FilterConfigItem* pConfigItem = NULL, WMF_EXTERNALHEADER *pExtHeader = NULL ); SVT_DLLPUBLIC sal_Bool ReadWindowMetafile( SvStream& rStream, GDIMetaFile& rMTF, FilterConfigItem* pConfigItem ); diff --git a/svtools/source/filter/filter.cxx b/svtools/source/filter/filter.cxx index 4cdd34d8c862..8548364e5e46 100644 --- a/svtools/source/filter/filter.cxx +++ b/svtools/source/filter/filter.cxx @@ -1329,9 +1329,9 @@ sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const INetURLObject& } sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const String& rPath, SvStream& rIStream, - sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, sal_uInt32 nImportFlags, WMF_APMFILEHEADER *pAPMHeader ) + sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, sal_uInt32 nImportFlags, WMF_EXTERNALHEADER *pExtHeader ) { - return ImportGraphic( rGraphic, rPath, rIStream, nFormat, pDeterminedFormat, nImportFlags, NULL, pAPMHeader ); + return ImportGraphic( rGraphic, rPath, rIStream, nFormat, pDeterminedFormat, nImportFlags, NULL, pExtHeader ); } //------------------------------------------------------------------------- @@ -1339,7 +1339,7 @@ sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const String& rPath, sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const String& rPath, SvStream& rIStream, sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, sal_uInt32 nImportFlags, com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData, - WMF_APMFILEHEADER *pAPMHeader ) + WMF_EXTERNALHEADER *pExtHeader ) { String aFilterName; sal_uLong nStmBegin; @@ -1554,7 +1554,7 @@ sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const String& rPath, aFilterName.EqualsIgnoreCaseAscii( IMP_EMF ) ) { GDIMetaFile aMtf; - if( !ConvertWMFToGDIMetaFile( rIStream, aMtf, NULL, pAPMHeader ) ) + if( !ConvertWMFToGDIMetaFile( rIStream, aMtf, NULL, pExtHeader ) ) nStatus = GRFILTER_FORMATERROR; else { diff --git a/svtools/source/filter/wmf/winmtf.hxx b/svtools/source/filter/wmf/winmtf.hxx index 58bb5bf25153..28c19c061eab 100644 --- a/svtools/source/filter/wmf/winmtf.hxx +++ b/svtools/source/filter/wmf/winmtf.hxx @@ -156,7 +156,7 @@ struct LOGFONTW sal_uInt8 lfPitchAndFamily; String alfFaceName; }; -struct WMF_APMFILEHEADER; +struct WMF_EXTERNALHEADER; #define TA_NOUPDATECP 0x0000 #define TA_UPDATECP 0x0001 @@ -872,8 +872,10 @@ private: sal_uInt32 nCurrentAction; sal_uInt32 nUnicodeEscapeAction; + WMF_EXTERNALHEADER* pExternalHeader; + // Liesst den Kopf der WMF-Datei - sal_Bool ReadHeader( WMF_APMFILEHEADER *pAPMHeader ); + sal_Bool ReadHeader(); // Liesst die Parameter des Rocords mit der Funktionsnummer nFunction. void ReadRecordParams( sal_uInt16 nFunction ); @@ -889,16 +891,18 @@ public: WMFReader( SvStream& rStreamWMF, GDIMetaFile& rGDIMetaFile, - FilterConfigItem* pConfigItem = NULL + FilterConfigItem* pConfigItem = NULL, + WMF_EXTERNALHEADER* pExtHeader = NULL ) : WinMtf( new WinMtfOutput( rGDIMetaFile ), rStreamWMF, pConfigItem ) - , pEMFStream(NULL) + , pEMFStream(NULL), + pExternalHeader(pExtHeader) {} ~WMFReader(); // Liesst aus dem Stream eine WMF-Datei und fuellt das GDIMetaFile - void ReadWMF(WMF_APMFILEHEADER *pAPMHeader=NULL); + void ReadWMF(); }; #endif diff --git a/svtools/source/filter/wmf/winwmf.cxx b/svtools/source/filter/wmf/winwmf.cxx index c08f6e108f76..d1727fb51634 100644 --- a/svtools/source/filter/wmf/winwmf.cxx +++ b/svtools/source/filter/wmf/winwmf.cxx @@ -117,6 +117,27 @@ #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() @@ -998,7 +1019,7 @@ void WMFReader::ReadRecordParams( sal_uInt16 nFunc ) // ------------------------------------------------------------------------ -sal_Bool WMFReader::ReadHeader(WMF_APMFILEHEADER *pAPMHeader) +sal_Bool WMFReader::ReadHeader() { sal_Size nStrmPos = pWMF->Tell(); @@ -1038,17 +1059,19 @@ sal_Bool WMFReader::ReadHeader(WMF_APMFILEHEADER *pAPMHeader) } else { - nUnitsPerInch = (pAPMHeader!=NULL?pAPMHeader->inch:96); + nUnitsPerInch = 96; pWMF->Seek( nStrmPos + 18 ); // set the streampos to the start of the the metaactions GetPlaceableBound( aPlaceableBound, pWMF ); pWMF->Seek( nStrmPos ); - if (pAPMHeader!=NULL) + if ( pExternalHeader != NULL && ( pExternalHeader->mapMode == MM_ISOTROPIC + || pExternalHeader->mapMode == MM_ANISOTROPIC ) ) { // #n417818#: If we have an external header then overwrite the bounds! - aPlaceableBound=Rectangle(pAPMHeader->left*567*nUnitsPerInch/1440/1000, - pAPMHeader->top*567*nUnitsPerInch/1440/1000, - pAPMHeader->right*567*nUnitsPerInch/1440/1000, - pAPMHeader->bottom*567*nUnitsPerInch/1440/1000); + 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 ); } } @@ -1087,7 +1110,7 @@ sal_Bool WMFReader::ReadHeader(WMF_APMFILEHEADER *pAPMHeader) return pWMF->good(); } -void WMFReader::ReadWMF(WMF_APMFILEHEADER *pAPMHeader) +void WMFReader::ReadWMF() { sal_uInt16 nFunction; sal_uLong nPos, nPercent, nLastPercent; @@ -1112,7 +1135,7 @@ void WMFReader::ReadWMF(WMF_APMFILEHEADER *pAPMHeader) pWMF->Seek( nStartPos ); Callback( (sal_uInt16) ( nLastPercent = 0 ) ); - if ( ReadHeader( pAPMHeader ) ) + if ( ReadHeader( ) ) { nPos = pWMF->Tell(); @@ -1207,27 +1230,6 @@ void WMFReader::ReadWMF(WMF_APMFILEHEADER *pAPMHeader) // ------------------------------------------------------------------------ -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 ); -} - sal_Bool WMFReader::GetPlaceableBound( Rectangle& rPlaceableBound, SvStream* pStm ) { sal_Bool bRet = sal_True; diff --git a/svtools/source/filter/wmf/wmf.cxx b/svtools/source/filter/wmf/wmf.cxx index 479ec5b30f86..3f3e5157855f 100644 --- a/svtools/source/filter/wmf/wmf.cxx +++ b/svtools/source/filter/wmf/wmf.cxx @@ -37,7 +37,7 @@ // ----------------------------------------------------------------------------- -sal_Bool ConvertWMFToGDIMetaFile( SvStream & rStreamWMF, GDIMetaFile & rGDIMetaFile, FilterConfigItem* pConfigItem, WMF_APMFILEHEADER *pAPMHeader ) +sal_Bool ConvertWMFToGDIMetaFile( SvStream & rStreamWMF, GDIMetaFile & rGDIMetaFile, FilterConfigItem* pConfigItem, WMF_EXTERNALHEADER *pExtHeader ) { sal_uInt32 nMetaType; sal_uInt32 nOrgPos = rStreamWMF.Tell(); @@ -53,7 +53,7 @@ sal_Bool ConvertWMFToGDIMetaFile( SvStream & rStreamWMF, GDIMetaFile & rGDIMetaF } else { - WMFReader( rStreamWMF, rGDIMetaFile, pConfigItem ).ReadWMF( pAPMHeader ); + WMFReader( rStreamWMF, rGDIMetaFile, pConfigItem, pExtHeader ).ReadWMF( ); } rStreamWMF.SetNumberFormatInt( nOrigNumberFormat ); return !rStreamWMF.GetError(); diff --git a/svtools/source/graphic/provider.cxx b/svtools/source/graphic/provider.cxx index 7807ffe24733..1bdc632e6310 100644 --- a/svtools/source/graphic/provider.cxx +++ b/svtools/source/graphic/provider.cxx @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -443,6 +444,8 @@ uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( co uno::Reference< io::XInputStream > xIStm; uno::Reference< awt::XBitmap >xBtm; + uno::Sequence< ::beans::PropertyValue > aFilterData; + for( sal_Int32 i = 0; ( i < rMediaProperties.getLength() ) && !pIStm && !xRet.is(); ++i ) { const ::rtl::OUString aName( rMediaProperties[ i ].Name ); @@ -462,6 +465,33 @@ uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( co { aValue >>= xBtm; } + else if( COMPARE_EQUAL == aName.compareToAscii( "FilterData" ) ) + { + aValue >>= aFilterData; + } + } + + // Check for the goal width and height if they are defined + sal_uInt16 nExtWidth = 0; + sal_uInt16 nExtHeight = 0; + sal_uInt16 nExtMapMode = 0; + for( sal_Int32 i = 0; i < aFilterData.getLength(); ++i ) + { + const ::rtl::OUString aName( aFilterData[ i ].Name ); + const uno::Any aValue( aFilterData[ i ].Value ); + + if( COMPARE_EQUAL == aName.compareToAscii( "ExternalWidth" ) ) + { + aValue >>= nExtWidth; + } + else if( COMPARE_EQUAL == aName.compareToAscii( "ExternalHeight" ) ) + { + aValue >>= nExtHeight; + } + else if( COMPARE_EQUAL == aName.compareToAscii( "ExternalMapMode" ) ) + { + aValue >>= nExtMapMode; + } } if( xIStm.is() ) @@ -499,7 +529,17 @@ uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( co { ::Graphic aVCLGraphic; - if( ( rFilter.ImportGraphic( aVCLGraphic, aPath, *pIStm ) == GRFILTER_OK ) && + // Define APM Header if goal height and width are defined + WMF_EXTERNALHEADER aExtHeader; + aExtHeader.xExt = nExtWidth; + aExtHeader.yExt = nExtHeight; + aExtHeader.mapMode = nExtMapMode; + WMF_EXTERNALHEADER *pExtHeader = NULL; + if ( nExtMapMode > 0 ) + pExtHeader = &aExtHeader; + + if( ( rFilter.ImportGraphic( aVCLGraphic, aPath, *pIStm, + GRFILTER_FORMAT_DONTKNOW, NULL, 0, pExtHeader ) == GRFILTER_OK ) && ( aVCLGraphic.GetType() != GRAPHIC_NONE ) ) { ::unographic::Graphic* pUnoGraphic = new ::unographic::Graphic; -- cgit