diff options
author | Bartosz Kosiorek <gang65@poczta.onet.pl> | 2021-06-05 19:30:46 +0200 |
---|---|---|
committer | Bartosz Kosiorek <gang65@poczta.onet.pl> | 2021-06-05 20:20:24 +0200 |
commit | 33d2cf7008de79106b5da4bba0241aa14d81d88f (patch) | |
tree | cccfea3a55086a0fcb9a0c089d7cbfc72ca5dfc7 /emfio | |
parent | 399a6472f666ae6c3e20b6f8367f9fd089c15605 (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.hxx | 2 | ||||
-rw-r--r-- | emfio/qa/cppunit/emf/EmfImportTest.cxx | 34 | ||||
-rw-r--r-- | emfio/qa/cppunit/wmf/data/TestStretchDIB.wmf | bin | 0 -> 612 bytes | |||
-rw-r--r-- | emfio/source/reader/wmfreader.cxx | 115 |
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 Binary files differnew file mode 100644 index 000000000000..c828debbc26e --- /dev/null +++ b/emfio/qa/cppunit/wmf/data/TestStretchDIB.wmf 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() ); |