vcl/qa/cppunit/svm/svmtest.cxx |   36 ++++++++++++++-------
 vcl/source/gdi/mtfxmldump.cxx  |   70 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 89 insertions(+), 17 deletions(-)

New commits:
commit 28edd79792a4b0ae7665a23bfbebb9499416daef
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Sat Jan 14 16:45:15 2023 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Sun Jan 15 08:07:41 2023 +0000

    vcl: add more device independent checks for bitmaps in svmtest
    
    Adds writing of "contentchecksum" to MetafileXmlDump, which sums
    the content of all the colors in an device independent way, by
    reading the each pixel color from the bitmap and summing each
    component always in RGBA order.
    
    In addition add some others bitmap attributes not checked before,
    like bitmap width, height and pixel format.
    
    Change-Id: I3bb5f7f6342766df235af71a4682a5d3ce17ab44
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145500
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/vcl/qa/cppunit/svm/svmtest.cxx b/vcl/qa/cppunit/svm/svmtest.cxx
index 02cec9bcfd45..e8925ffda064 100644
--- a/vcl/qa/cppunit/svm/svmtest.cxx
+++ b/vcl/qa/cppunit/svm/svmtest.cxx
@@ -1005,8 +1005,7 @@ void SvmTest::checkBitmapExs(const GDIMetaFile& 
rMetaFile, bool bIsSvmFile)
     if (SkiaHelper::isVCLSkiaEnabled())
         return; // TODO SKIA using CRCs is broken (the idea of it)
 
-    std::vector<OUString> aExpectedCRC;
-    aExpectedCRC.insert(aExpectedCRC.end(),
+    std::array<OUString, 8> aExpectedCRC
     {
 #if defined OSL_BIGENDIAN
         "08feb5d3",
@@ -1027,39 +1026,54 @@ void SvmTest::checkBitmapExs(const GDIMetaFile& 
rMetaFile, bool bIsSvmFile)
         "3c80d829",
         "71efc447",
 #endif
-    });
+    };
+
+    std::array<OUString, 8> aExpectedContentChecksum
+    {
+        "26bdebd04e5b18d685cea04982179e273ee3b659",
+        "f4f52df6ef965a2f0fbccbe6aca35ba3457cf9d5",
+        "7c953a06d34bbd38897f950d595df2880dbb0f75",
+        "ca3e5cdde1c395e1ee76d339a5bf6e46fbac3249",
+        "8a1ebc46f890eb0879464c6e293bffd4ce7fadc0", // 1-bit
+        "23611fc9f484c23e45bbd457730adb8ab5355509", // 4-bit color bitmap - 
same as 8-bit color bitmap
+        "23611fc9f484c23e45bbd457730adb8ab5355509",
+        "97e499b74104debf12f99a774a2c4edc914d8900",
+    };
 
     assertXPathAttrs(pDoc, "/metafile/bmpex[1]", {
-        {"x", "1"}, {"y", "1"}, {"crc", aExpectedCRC[0]}, {"transparenttype", 
"bitmap"}
+        {"x", "1"}, {"y", "1"}, {"crc", aExpectedCRC[0]}, {"transparenttype", 
"bitmap"}, {"contentchecksum", aExpectedContentChecksum[0]}, {"pixelformat", 
"24BPP"}
     });
     assertXPathAttrs(pDoc, "/metafile/bmpexscale[1]", {
         {"x", "5"}, {"y", "0"}, {"width", "2"}, {"height", "3"},
-        {"crc", aExpectedCRC[1]}, {"transparenttype", "bitmap"}
+        {"crc", aExpectedCRC[1]}, {"transparenttype", "bitmap"}, 
{"contentchecksum", aExpectedContentChecksum[1]}, {"pixelformat", "24BPP"}
     });
     assertXPathAttrs(pDoc, "/metafile/bmpexscalepart[1]", {
         {"destx", "7"}, {"desty", "1"}, {"destwidth", "2"}, {"destheight", 
"2"},
         {"srcx", "0"},  {"srcy", "0"},  {"srcwidth", "3"},  {"srcheight", "4"},
-        {"crc", aExpectedCRC[2]}, {"transparenttype", "bitmap"}
+        {"crc", aExpectedCRC[2]}, {"transparenttype", "bitmap"}, 
{"contentchecksum", aExpectedContentChecksum[2]}, {"pixelformat", "24BPP"}
     });
 
 #ifndef MACOSX
     assertXPathAttrs(pDoc, "/metafile/bmpex[2]", {
-        {"x", "6"}, {"y", "6"}, {"crc", aExpectedCRC[3]}, {"transparenttype", 
"bitmap"}
+        {"x", "6"}, {"y", "6"}, {"crc", aExpectedCRC[3]}, {"transparenttype", 
"bitmap"}, {"contentchecksum", aExpectedContentChecksum[3]}
+    });
+    assertXPathAttrs(pDoc, "/metafile/bmpex[3]", {
+            {"x", "0"}, {"y", "6"}, {"transparenttype", "bitmap"}, 
{"contentchecksum", aExpectedContentChecksum[4]}, {"pixelformat", "8BPP"}
     });
     if (!bIsSvmFile)
     {
         assertXPathAttrs(pDoc, "/metafile/bmpex[3]", {
-            {"x", "0"}, {"y", "6"}, {"crc", aExpectedCRC[4]}, 
{"transparenttype", "bitmap"}
+            {"crc", aExpectedCRC[4]}
         });
     }
     assertXPathAttrs(pDoc, "/metafile/bmpex[4]", {
-        {"x", "2"}, {"y", "6"}, {"crc", aExpectedCRC[5]}, {"transparenttype", 
"bitmap"}
+        {"x", "2"}, {"y", "6"}, {"crc", aExpectedCRC[5]}, {"transparenttype", 
"bitmap"}, {"contentchecksum", aExpectedContentChecksum[5]}, {"pixelformat", 
"8BPP"}
     });
     assertXPathAttrs(pDoc, "/metafile/bmpex[5]", {
-        {"x", "0"}, {"y", "8"}, {"crc", aExpectedCRC[6]}, {"transparenttype", 
"bitmap"}
+        {"x", "0"}, {"y", "8"}, {"crc", aExpectedCRC[6]}, {"transparenttype", 
"bitmap"}, {"contentchecksum", aExpectedContentChecksum[6]}, {"pixelformat", 
"8BPP"}
     });
     assertXPathAttrs(pDoc, "/metafile/bmpex[6]", {
-        {"x", "2"}, {"y", "8"}, {"crc", aExpectedCRC[7]}, {"transparenttype", 
"bitmap"}
+        {"x", "2"}, {"y", "8"}, {"crc", aExpectedCRC[7]}, {"transparenttype", 
"bitmap"}, {"contentchecksum", aExpectedContentChecksum[7]}, {"pixelformat", 
"8BPP"}
     });
 #else
     (void)bIsSvmFile;
diff --git a/vcl/source/gdi/mtfxmldump.cxx b/vcl/source/gdi/mtfxmldump.cxx
index d95578dbb9da..bda1c8f9843b 100644
--- a/vcl/source/gdi/mtfxmldump.cxx
+++ b/vcl/source/gdi/mtfxmldump.cxx
@@ -13,9 +13,14 @@
 
 #include <vcl/metaact.hxx>
 #include <vcl/outdev.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+
 #include <rtl/string.hxx>
 #include <rtl/ustrbuf.hxx>
 
+#include <comphelper/hash.hxx>
+
 #include <sstream>
 
 namespace
@@ -562,6 +567,53 @@ void writeGradient(tools::XmlWriter& rWriter, Gradient 
const& rGradient)
     rWriter.attribute("steps", rGradient.GetSteps());
 }
 
+OString toHexString(const std::vector<unsigned char>& a)
+{
+    std::stringstream aStrm;
+    for (auto& i : a)
+    {
+        aStrm << std::setw(2) << std::setfill('0') << std::hex << 
static_cast<int>(i);
+    }
+
+    return OString(aStrm.str().c_str());
+}
+
+void writeBitmapContentChecksum(tools::XmlWriter& rWriter, Bitmap const& 
rBitmap)
+{
+    Bitmap aBitmap(rBitmap);
+
+    comphelper::Hash aHashEngine(comphelper::HashType::SHA1);
+    Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+    assert(pReadAccess);
+
+    for (tools::Long y = 0 ; y < pReadAccess->Height() ; ++y)
+    {
+        for (tools::Long x = 0 ; x < pReadAccess->Width() ; ++x)
+        {
+            BitmapColor aColor = pReadAccess->GetColor(y, x);
+            sal_uInt8 r = aColor.GetRed();
+            sal_uInt8 g = aColor.GetGreen();
+            sal_uInt8 b = aColor.GetBlue();
+            sal_uInt8 a = aColor.GetAlpha();
+            aHashEngine.update(&r, 1);
+            aHashEngine.update(&g, 1);
+            aHashEngine.update(&b, 1);
+            aHashEngine.update(&a, 1);
+        }
+    }
+    std::vector<unsigned char> aVector = aHashEngine.finalize();
+    rWriter.attribute("contentchecksum", toHexString(aVector));
+}
+
+void writeBitmap(tools::XmlWriter& rWriter, Bitmap const& rBitmap)
+{
+    writeBitmapContentChecksum(rWriter, rBitmap);
+    rWriter.attribute("bitmapwidth", rBitmap.GetSizePixel().Width());
+    rWriter.attribute("bitmapheight", rBitmap.GetSizePixel().Height());
+    rWriter.attribute("pixelformat", 
convertPixelFormatToString(rBitmap.getPixelFormat()));
+    rWriter.attribute("crc", hex32(rBitmap.GetChecksum()));
+}
+
 } // anonymous namespace
 
 MetafileXmlDump::MetafileXmlDump()
@@ -880,9 +932,10 @@ void MetafileXmlDump::writeXml(const GDIMetaFile& 
rMetaFile, tools::XmlWriter& r
             case MetaActionType::BMP:
             {
                 auto pMeta = static_cast<MetaBmpAction*>(pAction);
+                Bitmap aBitmap = pMeta->GetBitmap();
                 rWriter.startElement(sCurrentElementTag);
                 writePoint(rWriter, pMeta->GetPoint());
-                rWriter.attribute("crc", 
hex32(pMeta->GetBitmap().GetChecksum()));
+                writeBitmap(rWriter, aBitmap);
                 rWriter.endElement();
             }
             break;
@@ -890,10 +943,11 @@ void MetafileXmlDump::writeXml(const GDIMetaFile& 
rMetaFile, tools::XmlWriter& r
             case MetaActionType::BMPSCALE:
             {
                 auto pMeta = static_cast<MetaBmpScaleAction*>(pAction);
+                Bitmap aBitmap = pMeta->GetBitmap();
                 rWriter.startElement(sCurrentElementTag);
                 writePoint(rWriter, pMeta->GetPoint());
                 writeSize(rWriter, pMeta->GetSize());
-                rWriter.attribute("crc", 
hex32(pMeta->GetBitmap().GetChecksum()));
+                writeBitmap(rWriter, aBitmap);
                 rWriter.endElement();
             }
             break;
@@ -901,6 +955,7 @@ void MetafileXmlDump::writeXml(const GDIMetaFile& 
rMetaFile, tools::XmlWriter& r
             case MetaActionType::BMPSCALEPART:
             {
                 auto pMeta = static_cast<MetaBmpScalePartAction*>(pAction);
+                Bitmap aBitmap = pMeta->GetBitmap();
                 rWriter.startElement(sCurrentElementTag);
                 rWriter.attribute("destx", pMeta->GetDestPoint().X());
                 rWriter.attribute("desty", pMeta->GetDestPoint().Y());
@@ -910,7 +965,7 @@ void MetafileXmlDump::writeXml(const GDIMetaFile& 
rMetaFile, tools::XmlWriter& r
                 rWriter.attribute("srcy", pMeta->GetSrcPoint().Y());
                 rWriter.attribute("srcwidth", pMeta->GetSrcSize().Width());
                 rWriter.attribute("srcheight", pMeta->GetSrcSize().Height());
-                rWriter.attribute("crc", 
hex32(pMeta->GetBitmap().GetChecksum()));
+                writeBitmap(rWriter, aBitmap);
                 rWriter.endElement();
             }
             break;
@@ -920,8 +975,9 @@ void MetafileXmlDump::writeXml(const GDIMetaFile& 
rMetaFile, tools::XmlWriter& r
                 auto pMeta = static_cast<MetaBmpExAction*>(pAction);
                 rWriter.startElement(sCurrentElementTag);
                 writePoint(rWriter, pMeta->GetPoint());
-                rWriter.attribute("crc", 
hex32(pMeta->GetBitmapEx().GetBitmap().GetChecksum()));
+                Bitmap aBitmap = pMeta->GetBitmapEx().GetBitmap();
                 rWriter.attribute("transparenttype", 
convertBitmapExTransparentType(pMeta->GetBitmapEx()));
+                writeBitmap(rWriter, aBitmap);
                 rWriter.endElement();
             }
             break;
@@ -932,8 +988,9 @@ void MetafileXmlDump::writeXml(const GDIMetaFile& 
rMetaFile, tools::XmlWriter& r
                 rWriter.startElement(sCurrentElementTag);
                 writePoint(rWriter, pMeta->GetPoint());
                 writeSize(rWriter, pMeta->GetSize());
-                rWriter.attribute("crc", 
hex32(pMeta->GetBitmapEx().GetBitmap().GetChecksum()));
+                Bitmap aBitmap = pMeta->GetBitmapEx().GetBitmap();
                 rWriter.attribute("transparenttype", 
convertBitmapExTransparentType(pMeta->GetBitmapEx()));
+                writeBitmap(rWriter, aBitmap);
                 rWriter.endElement();
             }
             break;
@@ -941,6 +998,7 @@ void MetafileXmlDump::writeXml(const GDIMetaFile& 
rMetaFile, tools::XmlWriter& r
             case MetaActionType::BMPEXSCALEPART:
             {
                 auto pMeta = static_cast<MetaBmpExScalePartAction*>(pAction);
+                Bitmap aBitmap = pMeta->GetBitmapEx().GetBitmap();
                 rWriter.startElement(sCurrentElementTag);
                 rWriter.attribute("destx", pMeta->GetDestPoint().X());
                 rWriter.attribute("desty", pMeta->GetDestPoint().Y());
@@ -950,8 +1008,8 @@ void MetafileXmlDump::writeXml(const GDIMetaFile& 
rMetaFile, tools::XmlWriter& r
                 rWriter.attribute("srcy", pMeta->GetSrcPoint().Y());
                 rWriter.attribute("srcwidth", pMeta->GetSrcSize().Width());
                 rWriter.attribute("srcheight", pMeta->GetSrcSize().Height());
-                rWriter.attribute("crc", 
hex32(pMeta->GetBitmapEx().GetBitmap().GetChecksum()));
                 rWriter.attribute("transparenttype", 
convertBitmapExTransparentType(pMeta->GetBitmapEx()));
+                writeBitmap(rWriter, aBitmap);
                 rWriter.endElement();
             }
             break;

Reply via email to