summaryrefslogtreecommitdiff
path: root/emfio
diff options
context:
space:
mode:
authorBartosz Kosiorek <gang65@poczta.onet.pl>2021-06-05 19:30:46 +0200
committerBartosz Kosiorek <gang65@poczta.onet.pl>2021-06-05 20:20:24 +0200
commit33d2cf7008de79106b5da4bba0241aa14d81d88f (patch)
treecccfea3a55086a0fcb9a0c089d7cbfc72ca5dfc7 /emfio
parent399a6472f666ae6c3e20b6f8367f9fd089c15605 (diff)
WMF Change the sign of read fields in BITBLT and DIB records
Additionally the names of variables were improved, and additional checks were added for unsupported cases Change-Id: Id84ef1218c5c2a40c8d01f2d40857d892badbb9f Change-Id: I1b8571d0a627827bc1e67c2bfc6c1932d58c5233 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116744 Tested-by: Jenkins Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
Diffstat (limited to 'emfio')
-rw-r--r--emfio/inc/wmfreader.hxx2
-rw-r--r--emfio/qa/cppunit/emf/EmfImportTest.cxx34
-rw-r--r--emfio/qa/cppunit/wmf/data/TestStretchDIB.wmfbin0 -> 612 bytes
-rw-r--r--emfio/source/reader/wmfreader.cxx115
4 files changed, 103 insertions, 48 deletions
diff --git a/emfio/inc/wmfreader.hxx b/emfio/inc/wmfreader.hxx
index 9e1059d63760..279f3e4caeee 100644
--- a/emfio/inc/wmfreader.hxx
+++ b/emfio/inc/wmfreader.hxx
@@ -55,7 +55,7 @@ namespace emfio
bool ReadHeader();
// reads parameters of the record with the functionnumber nFunction.
- void ReadRecordParams(sal_uInt16 nFunction);
+ void ReadRecordParams(sal_uInt32 nRecordSize, sal_uInt16 nFunction);
Point ReadPoint(); // reads and converts a point (first X then Y)
Point ReadYX(); // reads and converts a point (first Y then X)
diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx b/emfio/qa/cppunit/emf/EmfImportTest.cxx
index 1613fe943e6f..2ad512d0bac1 100644
--- a/emfio/qa/cppunit/emf/EmfImportTest.cxx
+++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx
@@ -65,6 +65,7 @@ class Test : public test::BootstrapFixture, public XmlTestTools, public unotest:
void TestExtTextOutOpaqueAndClipWMF();
void TestPaletteWMF();
void TestRoundrectWMF();
+ void TestStretchDIBWMF();
void TestPolylinetoCloseStroke();
void TestPolyLineWidth();
void TestRoundRect();
@@ -98,6 +99,7 @@ public:
CPPUNIT_TEST(TestExtTextOutOpaqueAndClipWMF);
CPPUNIT_TEST(TestPaletteWMF);
CPPUNIT_TEST(TestRoundrectWMF);
+ CPPUNIT_TEST(TestStretchDIBWMF);
CPPUNIT_TEST(TestPolylinetoCloseStroke);
CPPUNIT_TEST(TestPolyLineWidth);
CPPUNIT_TEST(TestRoundRect);
@@ -685,6 +687,38 @@ void Test::TestRoundrectWMF()
"width", "143");
}
+void Test::TestStretchDIBWMF()
+{
+ // WMF records: STRETCHDIB
+ Primitive2DSequence aSequence = parseEmf(u"/emfio/qa/cppunit/wmf/data/TestStretchDIB.wmf");
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));
+ drawinglayer::Primitive2dXmlDump dumper;
+ xmlDocUniquePtr pDocument = dumper.dumpAndParse(comphelper::sequenceToContainer<Primitive2DContainer>(aSequence));
+ CPPUNIT_ASSERT (pDocument);
+
+ assertXPath(pDocument, "/primitive2D/metafile/transform/bitmap",
+ "xy11", "12065");
+ assertXPath(pDocument, "/primitive2D/metafile/transform/bitmap",
+ "xy12", "0");
+ assertXPath(pDocument, "/primitive2D/metafile/transform/bitmap",
+ "xy13", "3598");
+ assertXPath(pDocument, "/primitive2D/metafile/transform/bitmap",
+ "xy21", "0");
+ assertXPath(pDocument, "/primitive2D/metafile/transform/bitmap",
+ "xy22", "12065");
+ assertXPath(pDocument, "/primitive2D/metafile/transform/bitmap",
+ "xy23", "3598");
+
+ assertXPath(pDocument, "/primitive2D/metafile/transform/bitmap",
+ "height", "10");
+ assertXPath(pDocument, "/primitive2D/metafile/transform/bitmap",
+ "width", "10");
+#if !defined(MACOSX) // TODO DIB display needs to be fixed for macOS
+ assertXPath(pDocument, "/primitive2D/metafile/transform/bitmap",
+ "checksum", "275245357");
+#endif
+}
+
void Test::TestPolyLineWidth()
{
// EMF import with records: CREATEPEN, ROUNDRECT.
diff --git a/emfio/qa/cppunit/wmf/data/TestStretchDIB.wmf b/emfio/qa/cppunit/wmf/data/TestStretchDIB.wmf
new file mode 100644
index 000000000000..c828debbc26e
--- /dev/null
+++ b/emfio/qa/cppunit/wmf/data/TestStretchDIB.wmf
Binary files differ
diff --git a/emfio/source/reader/wmfreader.cxx b/emfio/source/reader/wmfreader.cxx
index b3998e2e811b..7cd98315adef 100644
--- a/emfio/source/reader/wmfreader.cxx
+++ b/emfio/source/reader/wmfreader.cxx
@@ -279,7 +279,7 @@ namespace emfio
return Size( nW, nH );
}
- void WmfReader::ReadRecordParams( sal_uInt16 nFunc )
+ void WmfReader::ReadRecordParams( sal_uInt32 nRecordSize, sal_uInt16 nFunc )
{
SAL_INFO("emfio", "\t" << record_type_name(nFunc));
switch( nFunc )
@@ -803,7 +803,7 @@ namespace emfio
case W_META_BITBLT:
{
- // 0-3 : nWinROP #93454#
+ // 0-3 : nRasterOperation #93454#
// 4-5 : y offset of source bitmap
// 6-7 : x offset of source bitmap
// 8-9 : used height of source bitmap
@@ -817,16 +817,23 @@ namespace emfio
// 24 : planes
// 25 : bitcount
- sal_Int32 nWinROP = 0;
- sal_uInt16 nSx = 0, nSy = 0, nSxe = 0, nSye = 0, nDontKnow = 0, nWidth = 0, nHeight = 0, nBytesPerScan = 0;
+ sal_uInt32 nRasterOperation = 0;
+ sal_uInt16 nYSrc = 0, nXSrc = 0, nSye = 0, nSxe = 0, nBitmapType = 0, nWidth = 0, nHeight = 0, nBytesPerScan = 0;
sal_uInt8 nPlanes, nBitCount;
- mpInputStream->ReadInt32( nWinROP )
- .ReadUInt16( nSy ).ReadUInt16( nSx ).ReadUInt16( nSye ).ReadUInt16( nSxe );
- Point aPoint( ReadYX() );
- mpInputStream->ReadUInt16( nDontKnow ).ReadUInt16( nWidth ).ReadUInt16( nHeight ).ReadUInt16( nBytesPerScan ).ReadUChar( nPlanes ).ReadUChar( nBitCount );
+ mpInputStream->ReadUInt32( nRasterOperation );
+ SAL_WARN("emfio", "\t\t Raster operation: 0x" << std::hex << nRasterOperation << std::dec);
+ if ( nRecordSize == ( ( static_cast< sal_uInt32 >( nFunc ) >> 8 ) + 3 ) )
+ {
+ SAL_WARN("emfio", "\t\t TODO The Bitmap record detected without Bitmap. This case in not supported. Please fill a bug.");
+ break;
+ }
+ mpInputStream->ReadUInt16( nYSrc ).ReadUInt16( nXSrc ).ReadUInt16( nSye ).ReadUInt16( nSxe );
+ Point aPoint( ReadYX() ); // The upper-left corner of the destination rectangle.
+ mpInputStream->ReadUInt16( nBitmapType ).ReadUInt16( nWidth ).ReadUInt16( nHeight ).ReadUInt16( nBytesPerScan ).ReadUChar( nPlanes ).ReadUChar( nBitCount );
- bool bOk = nWidth && nHeight && nPlanes == 1 && nBitCount == 1 && nBytesPerScan != 0;
+ SAL_INFO("emfio", "\t\t Bitmap type:" << nBitmapType << " Width:" << nWidth << " Height:" << nHeight << " WidthBytes:" << nBytesPerScan);
+ bool bOk = nWidth && nHeight && nBytesPerScan > 0 && nPlanes == 1 && nBitCount == 1;
if (bOk)
{
// must be enough data to fulfil the request
@@ -859,63 +866,73 @@ namespace emfio
}
BitmapEx aBitmap = vcl::bitmap::CreateFromData(std::move(aBmp));
if ( nSye && nSxe &&
- ( nSx + nSxe <= nWidth ) &&
- ( nSy + nSye <= nHeight ) )
+ ( nXSrc + nSxe <= nWidth ) &&
+ ( nYSrc + nSye <= nHeight ) )
{
- tools::Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
+ tools::Rectangle aCropRect( Point( nXSrc, nYSrc ), Size( nSxe, nSye ) );
aBitmap.Crop( aCropRect );
}
tools::Rectangle aDestRect( aPoint, Size( nSxe, nSye ) );
- maBmpSaveList.emplace_back(new BSaveStruct(aBitmap, aDestRect, nWinROP));
+ maBmpSaveList.emplace_back(new BSaveStruct(aBitmap, aDestRect, nRasterOperation));
}
}
break;
- case W_META_STRETCHBLT:
case W_META_DIBBITBLT:
case W_META_DIBSTRETCHBLT:
+ case W_META_STRETCHBLT:
case W_META_STRETCHDIB:
{
- sal_Int32 nWinROP = 0;
- sal_uInt16 nSx = 0, nSy = 0, nSxe = 0, nSye = 0, nUsage = 0;
+ sal_uInt32 nRasterOperation = 0;
+ sal_Int16 nYSrc = 0, nXSrc = 0, nSrcHeight = 0, nSrcWidth = 0;
+ sal_uInt16 nColorUsage = 0;
Bitmap aBmp;
- mpInputStream->ReadInt32( nWinROP );
+ mpInputStream->ReadUInt32( nRasterOperation );
+ SAL_WARN("emfio", "\t\t Raster operation: 0x" << std::hex << nRasterOperation << std::dec);
+ if ( nRecordSize == ( ( static_cast< sal_uInt32 >( nFunc ) >> 8 ) + 3 ) )
+ {
+ SAL_WARN("emfio", "\t\t TODO The Bitmap record detected without Bitmap. This case in not supported. Please fill a bug.");
+ break;
+ }
if( nFunc == W_META_STRETCHDIB )
- mpInputStream->ReadUInt16( nUsage );
+ mpInputStream->ReadUInt16( nColorUsage );
- // nSye and nSxe is the number of pixels that has to been used
+ // nSrcHeight and nSrcWidth is the number of pixels that has to been used
// If they are set to zero, it is as indicator not to scale the bitmap later
+ if( nFunc == W_META_DIBSTRETCHBLT ||
+ nFunc == W_META_STRETCHBLT ||
+ nFunc == W_META_STRETCHDIB )
+ mpInputStream->ReadInt16( nSrcHeight ).ReadInt16( nSrcWidth );
- if( nFunc == W_META_STRETCHDIB || nFunc == W_META_STRETCHBLT || nFunc == W_META_DIBSTRETCHBLT )
- mpInputStream->ReadUInt16( nSye ).ReadUInt16( nSxe );
-
- // nSy and nx is the offset of the first pixel
- mpInputStream->ReadUInt16( nSy ).ReadUInt16( nSx );
+ // nYSrc and nXSrc is the offset of the first pixel
+ mpInputStream->ReadInt16( nYSrc ).ReadInt16( nXSrc );
- if( nFunc == W_META_STRETCHDIB || nFunc == W_META_DIBBITBLT || nFunc == W_META_DIBSTRETCHBLT )
+ if( nFunc == W_META_DIBBITBLT ||
+ nFunc == W_META_DIBSTRETCHBLT ||
+ nFunc == W_META_STRETCHDIB )
{
- if ( nWinROP == PATCOPY )
- mpInputStream->ReadUInt16( nUsage ); // i don't know anything of this parameter, so it's called nUsage
+ if ( nRasterOperation == PATCOPY )
+ mpInputStream->ReadUInt16( nColorUsage ); // i don't know anything of this parameter, so it's called nUsage
// DrawRect( Rectangle( ReadYX(), aDestSize ), false );
Size aDestSize( ReadYXExt() );
if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
{
tools::Rectangle aDestRect( ReadYX(), aDestSize );
- if ( nWinROP != PATCOPY )
+ if ( nRasterOperation != PATCOPY )
ReadDIB(aBmp, *mpInputStream, false);
// test if it is sensible to crop
- if ( nSye && nSxe &&
- ( nSx + nSxe <= aBmp.GetSizePixel().Width() ) &&
- ( nSy + nSye <= aBmp.GetSizePixel().Height() ) )
+ if ( nSrcHeight && nSrcWidth &&
+ ( nXSrc + nSrcWidth <= aBmp.GetSizePixel().Width() ) &&
+ ( nYSrc + nSrcHeight <= aBmp.GetSizePixel().Height() ) )
{
- tools::Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
+ tools::Rectangle aCropRect( Point( nXSrc, nYSrc ), Size( nSrcWidth, nSrcHeight ) );
aBmp.Crop( aCropRect );
}
- maBmpSaveList.emplace_back(new BSaveStruct(aBmp, aDestRect, nWinROP));
+ maBmpSaveList.emplace_back(new BSaveStruct(aBmp, aDestRect, nRasterOperation));
}
}
}
@@ -1574,7 +1591,7 @@ namespace emfio
}
if ( !mnSkipActions)
- ReadRecordParams( nFunction );
+ ReadRecordParams( mnRecSize, nFunction );
else
mnSkipActions--;
@@ -1888,32 +1905,36 @@ namespace emfio
}
break;
case W_META_BITBLT:
- case W_META_STRETCHBLT:
case W_META_DIBBITBLT:
case W_META_DIBSTRETCHBLT:
+ case W_META_STRETCHBLT:
case W_META_STRETCHDIB:
{
- sal_Int32 nWinROP;
- sal_uInt16 nSx, nSy, nUsage;
- pStm->ReadInt32( nWinROP );
+ sal_uInt32 nRasterOperation;
+ sal_Int16 nYSrc, nXSrc;
+ sal_uInt16 nColorUsage;
+ pStm->ReadUInt32( nRasterOperation );
if( nFunction == W_META_STRETCHDIB )
- pStm->ReadUInt16( nUsage );
+ pStm->ReadUInt16( nColorUsage );
// nSye and nSxe is the number of pixels that has to been used
- if( nFunction == W_META_STRETCHDIB || nFunction == W_META_STRETCHBLT || nFunction == W_META_DIBSTRETCHBLT )
+ if( nFunction == W_META_DIBSTRETCHBLT ||
+ nFunction == W_META_STRETCHBLT ||
+ nFunction == W_META_STRETCHDIB )
{
- sal_uInt16 nSxe, nSye;
- pStm->ReadUInt16( nSye ).ReadUInt16( nSxe );
+ sal_Int16 nSrcHeight, nSrcWidth;
+ pStm->ReadInt16( nSrcHeight ).ReadInt16( nSrcWidth );
}
- // nSy and nx is the offset of the first pixel
- pStm->ReadUInt16( nSy ).ReadUInt16( nSx );
+ // nYSrc and nXSrc is the offset of the first pixel
+ pStm->ReadInt16( nYSrc ).ReadInt16( nXSrc );
- if( nFunction == W_META_STRETCHDIB || nFunction == W_META_DIBBITBLT || nFunction == W_META_DIBSTRETCHBLT )
+ if( nFunction == W_META_DIBBITBLT ||
+ nFunction == W_META_DIBSTRETCHBLT )
{
- if ( nWinROP == PATCOPY )
- pStm->ReadUInt16( nUsage ); // i don't know anything of this parameter, so it's called nUsage
+ if ( nRasterOperation == PATCOPY )
+ pStm->ReadUInt16( nColorUsage ); // i don't know anything of this parameter, so it's called nUsage
// DrawRect( Rectangle( ReadYX(), aDestSize ), false );
Size aDestSize( ReadYXExt() );