diff options
-rw-r--r-- | drawinglayer/source/tools/primitive2dxmldump.cxx | 28 | ||||
-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 |
5 files changed, 131 insertions, 48 deletions
diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx index 24c390c7e0f3..295c13fde6e9 100644 --- a/drawinglayer/source/tools/primitive2dxmldump.cxx +++ b/drawinglayer/source/tools/primitive2dxmldump.cxx @@ -16,6 +16,7 @@ #include <memory> #include <sal/log.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx> #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> #include <drawinglayer/primitive2d/Tools.hxx> @@ -37,6 +38,7 @@ #include <basegfx/polygon/b2dpolypolygontools.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx> +#include <toolkit/helper/vclunohelper.hxx> using namespace drawinglayer::primitive2d; @@ -205,6 +207,32 @@ void Primitive2dXmlDump::decomposeAndWrite( switch (nId) { + case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D: + { + const BitmapPrimitive2D& rBitmapPrimitive2D = dynamic_cast<const BitmapPrimitive2D&>(*pBasePrimitive); + rWriter.startElement("bitmap"); + + basegfx::B2DHomMatrix const & rMatrix = rBitmapPrimitive2D.getTransform(); + rWriter.attribute("xy11", rMatrix.get(0,0)); + rWriter.attribute("xy12", rMatrix.get(0,1)); + rWriter.attribute("xy13", rMatrix.get(0,2)); + rWriter.attribute("xy21", rMatrix.get(1,0)); + rWriter.attribute("xy22", rMatrix.get(1,1)); + rWriter.attribute("xy23", rMatrix.get(1,2)); + rWriter.attribute("xy31", rMatrix.get(2,0)); + rWriter.attribute("xy32", rMatrix.get(2,1)); + rWriter.attribute("xy33", rMatrix.get(2,2)); + + const BitmapEx aBitmapEx(VCLUnoHelper::GetBitmap(rBitmapPrimitive2D.getXBitmap())); + const Size& rSizePixel(aBitmapEx.GetSizePixel()); + + rWriter.attribute("height", rSizePixel.getHeight()); + rWriter.attribute("width", rSizePixel.getWidth()); + rWriter.attribute("checksum", aBitmapEx.GetChecksum()); + + rWriter.endElement(); + } + break; case PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D: { const HiddenGeometryPrimitive2D& rHiddenGeometryPrimitive2D = dynamic_cast<const HiddenGeometryPrimitive2D&>(*pBasePrimitive); 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() ); |