[Libreoffice-commits] core.git: drawinglayer/source emfio/inc emfio/qa emfio/source

Bartosz Kosiorek (via logerrit) logerrit at kemper.freedesktop.org
Sat Jun 5 18:21:03 UTC 2021


 drawinglayer/source/tools/primitive2dxmldump.cxx |   28 +++++
 emfio/inc/wmfreader.hxx                          |    2 
 emfio/qa/cppunit/emf/EmfImportTest.cxx           |   34 ++++++
 emfio/qa/cppunit/wmf/data/TestStretchDIB.wmf     |binary
 emfio/source/reader/wmfreader.cxx                |  115 +++++++++++++----------
 5 files changed, 131 insertions(+), 48 deletions(-)

New commits:
commit 33d2cf7008de79106b5da4bba0241aa14d81d88f
Author:     Bartosz Kosiorek <gang65 at poczta.onet.pl>
AuthorDate: Sat Jun 5 19:30:46 2021 +0200
Commit:     Bartosz Kosiorek <gang65 at poczta.onet.pl>
CommitDate: Sat Jun 5 20:20:24 2021 +0200

    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 at poczta.onet.pl>

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
new file mode 100644
index 000000000000..c828debbc26e
Binary files /dev/null and b/emfio/qa/cppunit/wmf/data/TestStretchDIB.wmf 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() );


More information about the Libreoffice-commits mailing list