summaryrefslogtreecommitdiff
path: root/vcl/source/filter/wmf/enhwmf.cxx
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2016-01-22 11:39:41 +0100
committerArmin Le Grand <Armin.Le.Grand@cib.de>2016-01-29 12:02:11 +0000
commit6f12c93703b676b1b3839caaf2c21788e5d68477 (patch)
treeb62b26ed86f6e656ca66d85e828abd2475f03bc0 /vcl/source/filter/wmf/enhwmf.cxx
parent1d0f08cdf1b9396e97e068f97fd78f31b5906748 (diff)
tdf#91017 Enhance WMF import of EMR_ALPHABLEND action
The EMR_ALPHABLEND action was added 2012/2013, but missed support for Bitmaps with Mask/Alpha. Due to that files with WMF containing these actions may look different from before. Added suport to load contained Mask/Alpha information in DIBs and the needed additional processing through the display chain. WMF import is still based on Metafile creation, when it would be using Primitives more original data could be preserved. Change-Id: I577569848cee2528328181fa0c7eb7f87857d094 Reviewed-on: https://gerrit.libreoffice.org/21709 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Noel Grandin <noelgrandin@gmail.com> Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
Diffstat (limited to 'vcl/source/filter/wmf/enhwmf.cxx')
-rw-r--r--vcl/source/filter/wmf/enhwmf.cxx106
1 files changed, 89 insertions, 17 deletions
diff --git a/vcl/source/filter/wmf/enhwmf.cxx b/vcl/source/filter/wmf/enhwmf.cxx
index 3becfbe3ed57..f8341e3adecf 100644
--- a/vcl/source/filter/wmf/enhwmf.cxx
+++ b/vcl/source/filter/wmf/enhwmf.cxx
@@ -23,6 +23,11 @@
#include <vcl/dibtools.hxx>
#include <memory>
+#ifdef DBG_UTIL
+#include <tools/stream.hxx>
+#include <vcl/pngwrite.hxx>
+#endif
+
using namespace std;
// GDI-Array
@@ -1208,43 +1213,110 @@ bool EnhWMFReader::ReadEnhWMF()
.ReadUInt32( offBitsSrc ).ReadUInt32( cbBitsSrc ).ReadInt32( cxSrc ).ReadInt32( cySrc ) ;
sal_uInt32 dwRop = SRCAND|SRCINVERT;
-
- Bitmap aBitmap;
Rectangle aRect( Point( xDest, yDest ), Size( cxDest+1, cyDest+1 ) );
if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
bStatus = false;
else
{
- sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
- if ( nSize <= ( nEndPos - nStartPos ) )
+ const sal_uInt32 nSourceSize = cbBmiSrc + cbBitsSrc + 14;
+ if ( nSourceSize <= ( nEndPos - nStartPos ) )
{
- char* pBuf = new char[ nSize ];
- SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE );
+ // we need to read alpha channel data if AlphaFormat of BLENDFUNCTION is
+ // AC_SRC_ALPHA (==0x01). To read it, create a temp DIB-File which is ready
+ // for DIB-5 format
+ const bool bReadAlpha(0x01 == aFunc.aAlphaFormat);
+ const sal_uInt32 nDeltaToDIB5HeaderSize(bReadAlpha ? getDIBV5HeaderSize() - cbBmiSrc : 0);
+ const sal_uInt32 nTargetSize(cbBmiSrc + nDeltaToDIB5HeaderSize + cbBitsSrc + 14);
+ char* pBuf = new char[ nTargetSize ];
+ SvMemoryStream aTmp( pBuf, nTargetSize, StreamMode::READ | StreamMode::WRITE );
+
aTmp.ObjectOwnsMemory( true );
+
+ // write BM-Header (14 bytes)
aTmp.WriteUChar( 'B' )
.WriteUChar( 'M' )
.WriteUInt32( cbBitsSrc )
.WriteUInt16( 0 )
.WriteUInt16( 0 )
- .WriteUInt32( cbBmiSrc + 14 );
+ .WriteUInt32( cbBmiSrc + nDeltaToDIB5HeaderSize + 14 );
+
+ // copy DIBInfoHeader from source (cbBmiSrc bytes)
pWMF->Seek( nStart + offBmiSrc );
pWMF->Read( pBuf + 14, cbBmiSrc );
+
+ if(bReadAlpha)
+ {
+ // need to add values for all stuff that DIBV5Header is bigger
+ // than DIBInfoHeader, all values are correctly initialized to zero,
+ // so we can use memset here
+ memset(pBuf + cbBmiSrc + 14, 0, nDeltaToDIB5HeaderSize);
+ }
+
+ // copy bitmap data from source (offBitsSrc bytes)
pWMF->Seek( nStart + offBitsSrc );
- pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
+ pWMF->Read( pBuf + 14 + nDeltaToDIB5HeaderSize + cbBmiSrc, cbBitsSrc );
aTmp.Seek( 0 );
- ReadDIB(aBitmap, aTmp, 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() ) )
+ // prepare to read and fill BitmapEx
+ BitmapEx aBitmapEx;
+
+ if(bReadAlpha)
{
- Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
- aBitmap.Crop( aCropRect );
+ Bitmap aBitmap;
+ AlphaMask aAlpha;
+
+ if(ReadDIBV5(aBitmap, aAlpha, aTmp))
+ {
+ aBitmapEx = BitmapEx(aBitmap, aAlpha);
+ }
+ }
+ else
+ {
+ Bitmap aBitmap;
+
+ if(ReadDIB(aBitmap, aTmp, true))
+ {
+ if(0xff != aFunc.aSrcConstantAlpha)
+ {
+ // add const alpha channel
+ aBitmapEx = BitmapEx(
+ aBitmap,
+ AlphaMask(aBitmap.GetSizePixel(), &aFunc.aSrcConstantAlpha));
+ }
+ else
+ {
+ // just use Bitmap
+ aBitmapEx = BitmapEx(aBitmap);
+ }
+ }
+ }
+
+ if(!aBitmapEx.IsEmpty())
+ {
+ // test if it is sensible to crop
+ if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
+ ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
+ ( xSrc + cxSrc < aBitmapEx.GetSizePixel().Width() ) &&
+ ( ySrc + cySrc < aBitmapEx.GetSizePixel().Height() ) )
+ {
+ const Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
+
+ aBitmapEx.Crop( aCropRect );
+ }
+
+#ifdef DBG_UTIL
+ static bool bDoSaveForVisualControl(false);
+
+ if(bDoSaveForVisualControl)
+ {
+ SvFileStream aNew(OUString("c:\\metafile_content.png"), StreamMode::WRITE|StreamMode::TRUNC);
+ vcl::PNGWriter aPNGWriter(aBitmapEx);
+ aPNGWriter.Write(aNew);
+ }
+#endif
+ aBmpSaveList.emplace_back(new BSaveStruct(aBitmapEx, aRect, dwRop));
}
- aBmpSaveList.emplace_back(new BSaveStruct(aBitmap, aRect, dwRop));
}
}
}