sd/qa/unit/tiledrendering/tiledrendering.cxx |  885 +++++++++++++++++++--------
 1 file changed, 636 insertions(+), 249 deletions(-)

New commits:
commit c5e050943c53f01c6458107bcd3bf381d3c71062
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Wed Oct 23 21:02:47 2024 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Mar 17 10:29:22 2025 +0100

    slideshow: check JSON content for slideshow rendering test
    
    JSON checks were missing for most tests, while the other tests
    did check the JSON string directly instead of parsing it first.
    
    Change-Id: Ie0733acb24cd982e7e6be3ef719f8ef2e1345ffa
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183022
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx 
b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index 2790ce524015..752b324419b5 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -65,32 +65,6 @@
 
 using namespace css;
 
-namespace
-{
-
-void debugWriteImageToFile(unsigned step, const std::vector<sal_uInt8>& 
pBuffer,
-    unsigned nViewWidth, unsigned nViewHeight, const char* sJSON)
-{
-    (void)step;
-    (void)pBuffer;
-    (void)nViewWidth;
-    (void)nViewHeight;
-    (void)sJSON;
-
-#if false
-    printf ("%u %s

", step, sJSON);
-
-    BitmapEx aBitmapEx = vcl::bitmap::CreateFromData(pBuffer.data(), 
nViewWidth, nViewHeight, nViewWidth * 4, /*nBitsPerPixel*/32, true, true);
-
-    OUString sFileName = "/tmp/slideshow_" + OUString::number(step) + ".png";
-    SvFileStream aStream(sFileName, StreamMode::WRITE | StreamMode::TRUNC);
-    vcl::PngImageWriter aPNGWriter(aStream);
-    aPNGWriter.write(aBitmapEx);
-#endif
-}
-
-}
-
 static std::ostream& operator<<(std::ostream& os, ViewShellId id)
 {
     os << static_cast<sal_Int32>(id);
@@ -2707,6 +2681,34 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testStartPresentation)
 namespace
 {
 
+void debugWriteImageToFile(unsigned step, const std::vector<sal_uInt8>& 
pBuffer,
+    unsigned nViewWidth, unsigned nViewHeight, const char* sJSON)
+{
+    (void)step;
+    (void)pBuffer;
+    (void)nViewWidth;
+    (void)nViewHeight;
+    (void)sJSON;
+
+#if false
+    printf ("%u %s

", step, sJSON);
+
+    BitmapEx aBitmapEx = vcl::bitmap::CreateFromData(pBuffer.data(), 
nViewWidth, nViewHeight, nViewWidth * 4, /*nBitsPerPixel*/32, true, true);
+
+    OUString sFileName = "/tmp/slideshow_" + OUString::number(step) + ".png";
+    SvFileStream aStream(sFileName, StreamMode::WRITE | StreamMode::TRUNC);
+    vcl::PngImageWriter aPNGWriter(aStream);
+    aPNGWriter.write(aBitmapEx);
+#endif
+}
+
+template <typename T>
+bool is_unique(std::vector<T> vec)
+{
+    std::sort(vec.begin(), vec.end());
+    return std::unique(vec.begin(), vec.end()) == vec.end();
+}
+
 boost::property_tree::ptree const& child_at(boost::property_tree::ptree const& 
rTree, std::string_view aName, size_t nIndex)
 {
     return std::next(rTree.get_child(std::string(aName)).find(""), 
nIndex)->second;
@@ -2717,6 +2719,12 @@ bool has_child(boost::property_tree::ptree const& rTree, 
std::string_view aName)
     return rTree.count(std::string(aName)) > 0;
 }
 
+void readJSON(boost::property_tree::ptree& rTree, OUString const& rJson)
+{
+    std::stringstream aStream((std::string(rJson.toUtf8())));
+    boost::property_tree::read_json(aStream, rTree);
+}
+
 } // end anonymous ns
 
 CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testPresentationInfo)
@@ -2836,75 +2844,108 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering)
     CPPUNIT_ASSERT_EQUAL(1125, nViewHeight);
 
     const Color aTransparentColor(ColorAlpha, 0x00000000);
+    const tools::Long nLeft = 20;
+    const tools::Long nRight = nViewWidth - 20;
+    const tools::Long nTop = 20;
+    const tools::Long nBottom = nViewHeight - 20;
 
     // Background Layer - TODO
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+
+        debugWriteImageToFile(0, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("Background"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
         // TODO - check JSON content
 
         BitmapEx aBitmapEx = vcl::bitmap::CreateFromData(pBuffer.data(), 
nViewWidth, nViewHeight, nViewWidth * 4, /*nBitsPerPixel*/32, true, true);
-        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
 
         // top-left corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, 
20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(nLeft, 
nTop));
 
         // bottom-left corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, 
nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(nLeft, 
nBottom));
 
         // bottom-right corner
-        CPPUNIT_ASSERT_EQUAL(Color(0xff, 0xd0, 0x40), 
aBitmapEx.GetPixelColor(nViewWidth - 20, nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(Color(0xff, 0xd0, 0x40), 
aBitmapEx.GetPixelColor(nRight, nBottom));
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("MasterPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
         // TODO - check JSON content
-        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
 
         BitmapEx aBitmapEx = vcl::bitmap::CreateFromData(pBuffer.data(), 
nViewWidth, nViewHeight, nViewWidth * 4, /*nBitsPerPixel*/32, true, true);
 
         // top-left corner
-        CPPUNIT_ASSERT_EQUAL(Color(0x00, 0x50, 0x90), 
aBitmapEx.GetPixelColor(20, 20));
+        CPPUNIT_ASSERT_EQUAL(Color(0x00, 0x50, 0x90), 
aBitmapEx.GetPixelColor(nLeft, nTop));
 
         // bottom-left corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, 
nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(nLeft, 
nBottom));
 
         // bottom-right corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, 
aBitmapEx.GetPixelColor(nViewWidth - 20, nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, 
aBitmapEx.GetPixelColor(nRight, nBottom));
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+        CPPUNIT_ASSERT(aJson.isEmpty());
     }
+
     pXImpressDocument->postSlideshowCleanup();
 }
 
 CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_WithFields)
 {
-    // Check rendering of slideshow layers (as in the document):
-    // - master slide layer
-    // - main slide layer
+    // Check rendering of fields - each in own layer
 
     SdXImpressDocument* pXImpressDocument = 
createDoc("SlideRenderingTest_WithFields.odp");
     
pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
@@ -2921,114 +2962,160 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_WithFie
     CPPUNIT_ASSERT_EQUAL(1125, nViewHeight);
 
     const Color aTransparentColor(ColorAlpha, 0x00000000);
+    const tools::Long nLeft = 20;
+    const tools::Long nRight = nViewWidth - 20;
+    const tools::Long nTop = 20;
+    const tools::Long nBottom = nViewHeight - 20;
+    const tools::Long nCenterX = nViewWidth / 2;
 
-    // Background Layer - TODO
+    // Background Layer
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
-        debugWriteImageToFile(0, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+        debugWriteImageToFile(0, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("Background"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
-        // TODO - check JSON content
-        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+
+        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
 
         BitmapEx aBitmapEx = vcl::bitmap::CreateFromData(pBuffer.data(), 
nViewWidth, nViewHeight, nViewWidth * 4, /*nBitsPerPixel*/32, true, true);
 
         // top-left corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, 
20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(nLeft, 
nTop));
 
         // bottom-left corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, 
nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(nLeft, 
nBottom));
 
         // bottom-right corner
-        CPPUNIT_ASSERT_EQUAL(Color(0xff, 0xd0, 0x40), 
aBitmapEx.GetPixelColor(nViewWidth - 20, nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(Color(0xff, 0xd0, 0x40), 
aBitmapEx.GetPixelColor(nRight, nBottom));
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("MasterPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
         // TODO - check JSON content
-        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
 
         BitmapEx aBitmapEx = vcl::bitmap::CreateFromData(pBuffer.data(), 
nViewWidth, nViewHeight, nViewWidth * 4, /*nBitsPerPixel*/32, true, true);
 
         // top-left corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, 
20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(nLeft, 
nTop));
 
         // bottom-left corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, 
nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(nLeft, 
nBottom));
 
         // bottom-right corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, 
aBitmapEx.GetPixelColor(nViewWidth - 20, nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, 
aBitmapEx.GetPixelColor(nRight, nBottom));
 
         // bottom-center
-        CPPUNIT_ASSERT_EQUAL(Color(0x20, 0xaa, 0x00), 
aBitmapEx.GetPixelColor(nViewWidth / 2, nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(Color(0x20, 0xaa, 0x00), 
aBitmapEx.GetPixelColor(nCenterX, nBottom));
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("MasterPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(1, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
-        // TODO - check JSON content
-        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+
+        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
 
         BitmapEx aBitmapEx = vcl::bitmap::CreateFromData(pBuffer.data(), 
nViewWidth, nViewHeight, nViewWidth * 4, /*nBitsPerPixel*/32, true, true);
 
         // top-left corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, 
20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(nLeft, 
nTop));
 
         // bottom-left corner
-        CPPUNIT_ASSERT_EQUAL(Color(0x90, 0x80, 0xff), 
aBitmapEx.GetPixelColor(20, nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(Color(0x90, 0x80, 0xff), 
aBitmapEx.GetPixelColor(nLeft, nBottom));
 
         // bottom-right corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, 
aBitmapEx.GetPixelColor(nViewWidth - 20, nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, 
aBitmapEx.GetPixelColor(nRight, nBottom));
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("MasterPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(2, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
-        // TODO - check JSON content
-        debugWriteImageToFile(4, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+
+        debugWriteImageToFile(4, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
 
         BitmapEx aBitmapEx = vcl::bitmap::CreateFromData(pBuffer.data(), 
nViewWidth, nViewHeight, nViewWidth * 4, /*nBitsPerPixel*/32, true, true);
 
         // top-left corner
-        CPPUNIT_ASSERT_EQUAL(Color(0x00, 0x50, 0x90), 
aBitmapEx.GetPixelColor(20, 20));
+        CPPUNIT_ASSERT_EQUAL(Color(0x00, 0x50, 0x90), 
aBitmapEx.GetPixelColor(nLeft, nTop));
 
         // bottom-left corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(20, 
nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, aBitmapEx.GetPixelColor(nLeft, 
nBottom));
 
         // bottom-right corner
-        CPPUNIT_ASSERT_EQUAL(aTransparentColor, 
aBitmapEx.GetPixelColor(nViewWidth - 20, nViewHeight - 20));
+        CPPUNIT_ASSERT_EQUAL(aTransparentColor, 
aBitmapEx.GetPixelColor(nRight, nBottom));
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+        CPPUNIT_ASSERT(aJson.isEmpty());
     }
 
     pXImpressDocument->postSlideshowCleanup();
@@ -3036,6 +3123,8 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_WithFie
 
 CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animations)
 {
+    // Check rendering of animated objects - each in own layer
+
     SdXImpressDocument* pXImpressDocument = 
createDoc("SlideRenderingTest_Animations.odp");
     
pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
@@ -3053,98 +3142,139 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animati
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
+        debugWriteImageToFile(0, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"Background\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 0") >= 0);
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"hash\""));
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"initVisible\""));
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"bitmap\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"content\": { \"type\": 
\"%IMAGETYPE%\", \"checksum\": \"%IMAGECHECKSUM%\"}") >= 0);
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
 
-        debugWriteImageToFile(0, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(std::string("Background"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "initVisible"));
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
+        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"MasterPage\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 0") >= 0);
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"hash\""));
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"initVisible\""));
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"bitmap\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"content\": { \"type\": 
\"%IMAGETYPE%\", \"checksum\": \"%IMAGECHECKSUM%\"}") >= 0);
+        CPPUNIT_ASSERT_EQUAL(std::string("MasterPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
 
-        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "initVisible"));
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
+        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"MasterPage\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 1") >= 0);
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"hash\""));
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"initVisible\""));
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"bitmap\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"content\": { \"type\": 
\"%IMAGETYPE%\", \"checksum\": \"%IMAGECHECKSUM%\"}") >= 0);
+        CPPUNIT_ASSERT_EQUAL(std::string("MasterPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(1, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
 
-        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "initVisible"));
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
+        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"DrawPage\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 0") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"hash\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"animated\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"initVisible\": true") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"content\": { \"type\": 
\"%IMAGETYPE%\", \"checksum\": \"%IMAGECHECKSUM%\"}") >= 0);
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
 
-        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("animated"), 
aTree.get_child("type").get_value<std::string>());
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(std::string("true"), 
aContentChild.get_child("initVisible").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aContentChild.get_child("type").get_value<std::string>());
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "content"));
+        auto aContentChildChild = aContentChild.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChildChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChildChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
+        debugWriteImageToFile(4, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(1, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("animated"), 
aTree.get_child("type").get_value<std::string>());
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"DrawPage\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 1") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"hash\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"initVisible\": false") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"animated\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"content\": { \"type\": 
\"%IMAGETYPE%\", \"checksum\": \"%IMAGECHECKSUM%\"}") >= 0);
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
 
-        debugWriteImageToFile(4, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(std::string("false"), 
aContentChild.get_child("initVisible").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aContentChild.get_child("type").get_value<std::string>());
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "content"));
+        auto aContentChildChild = aContentChild.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChildChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChildChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+        CPPUNIT_ASSERT(aJson.isEmpty());
     }
 
     pXImpressDocument->postSlideshowCleanup();
@@ -3169,147 +3299,229 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animati
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"Background\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 0") >= 0);
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"hash\""));
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"initVisible\""));
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"bounds\""));
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"bitmap\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"content\": { \"type\": 
\"%IMAGETYPE%\", \"checksum\": \"%IMAGECHECKSUM%\"}") >= 0);
+        debugWriteImageToFile(0, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("Background"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
 
-        debugWriteImageToFile(0, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "initVisible"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "bounds"));
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"MasterPage\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 0") >= 0);
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"bounds\""));
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"bitmap\"") >= 0);
+        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("MasterPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
 
-        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "initVisible"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "bounds"));
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"MasterPage\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 1") >= 0);
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"bounds\""));
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"bitmap\"") >= 0);
+        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
 
-        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("MasterPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(1, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "initVisible"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "bounds"));
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"DrawPage\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 0") >= 0);
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"initVisible\""));
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"bounds\""));
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"bitmap\"") >= 0);
+        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
 
-        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "initVisible"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "bounds"));
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
-
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"DrawPage\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 1") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"initVisible\": false") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"animated\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"bitmap\"") >= 0);
+        debugWriteImageToFile(4, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
 
-        debugWriteImageToFile(4, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(1, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("animated"), 
aTree.get_child("type").get_value<std::string>());
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(std::string("false"), 
aContentChild.get_child("initVisible").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "bounds"));
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aContentChild.get_child("type").get_value<std::string>());
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "content"));
+        auto aContentChildChild = aContentChild.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChildChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChildChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"DrawPage\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 2") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"initVisible\": true") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"bounds\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"animated\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"bitmap\"") >= 0);
+        debugWriteImageToFile(5, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(2, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("animated"), 
aTree.get_child("type").get_value<std::string>());
 
-        debugWriteImageToFile(5, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(std::string("true"), 
aContentChild.get_child("initVisible").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "bounds"));
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aContentChild.get_child("type").get_value<std::string>());
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "content"));
+        auto aContentChildChild = aContentChild.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChildChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChildChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"DrawPage\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 3") >= 0);
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"initVisible\""));
-        CPPUNIT_ASSERT_EQUAL(-1, rJsonMsg.indexOf(u"\"bounds\""));
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"bitmap\"") >= 0);
+        debugWriteImageToFile(6, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(3, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
 
-        debugWriteImageToFile(6, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "initVisible"));
+        CPPUNIT_ASSERT_EQUAL(false, has_child(aContentChild, "bounds"));
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
         CPPUNIT_ASSERT(bIsBitmapLayer);
 
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"group\": \"DrawPage\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"index\": 4") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"initVisible\": false") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"bounds\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"animated\"") >= 0);
-        CPPUNIT_ASSERT(rJsonMsg.indexOf(u"\"type\": \"bitmap\"") >= 0);
+        debugWriteImageToFile(7, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(4, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("animated"), 
aTree.get_child("type").get_value<std::string>());
 
-        debugWriteImageToFile(7, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(std::string("false"), 
aContentChild.get_child("initVisible").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "bounds"));
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aContentChild.get_child("type").get_value<std::string>());
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "content"));
+        auto aContentChildChild = aContentChild.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChildChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChildChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+        CPPUNIT_ASSERT(aJson.isEmpty());
     }
 
     pXImpressDocument->postSlideshowCleanup();
@@ -3317,6 +3529,8 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animati
 
 CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animation_TextBox)
 {
+    // Check rendering of animated paragraphs in a text box
+
     SdXImpressDocument* pXImpressDocument = 
createDoc("SlideRenderingTest_TextBox.odp");
     
pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
@@ -3335,50 +3549,136 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animati
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+
+        debugWriteImageToFile(0, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("Background"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
 
-        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
 
-        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        debugWriteImageToFile(21, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+
+        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
 
-        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(1, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("animated"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(std::string("false"), 
aContentChild.get_child("initVisible").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "bounds"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "content"));
+        auto aContentChildChild = aContentChild.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChildChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChildChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+
+        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(2, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("animated"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(std::string("false"), 
aContentChild.get_child("initVisible").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "bounds"));
 
-        debugWriteImageToFile(4, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "content"));
+        auto aContentChildChild = aContentChild.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChildChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChildChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
 
-        debugWriteImageToFile(5, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        debugWriteImageToFile(4, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(3, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("animated"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(std::string("false"), 
aContentChild.get_child("initVisible").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "bounds"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "content"));
+        auto aContentChildChild = aContentChild.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChildChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChildChild.get_child("checksum").get_value<std::string>());
     }
 
     // Check we are done
@@ -3386,8 +3686,9 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animati
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+        CPPUNIT_ASSERT(aJson.isEmpty());
     }
 
     pXImpressDocument->postSlideshowCleanup();
@@ -3395,6 +3696,8 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animati
 
 CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animation_TextBox_SecondParagraphMultipleEffects)
 {
+    // Check rendering of animated paragraphs in a text box when there are 
multiple effects for one paragraph
+
     SdXImpressDocument* pXImpressDocument = 
createDoc("SlideRenderingTest_Animations_SecondParagraphMultipleEffects.odp");
     
pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
@@ -3413,30 +3716,76 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animati
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
 
-        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("Background"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+
+        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
 
-        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+
+        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(1, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("animated"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(std::string("false"), 
aContentChild.get_child("initVisible").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "bounds"));
 
-        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "content"));
+        auto aContentChildChild = aContentChild.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChildChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChildChild.get_child("checksum").get_value<std::string>());
     }
 
     // Check we are done
@@ -3444,23 +3793,14 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animati
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
         double dScale = 1.0;
-        OUString rJsonMsg;
-        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+        CPPUNIT_ASSERT(aJson.isEmpty());
     }
 
     pXImpressDocument->postSlideshowCleanup();
 }
 
-namespace
-{
-template <typename T>
-bool is_unique(std::vector<T> vec)
-{
-    std::sort(vec.begin(), vec.end());
-    return std::unique(vec.begin(), vec.end()) == vec.end();
-}
-}
-
 CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animation_DifferentKindOfTextBox)
 {
     SdXImpressDocument* pXImpressDocument = 
createDoc("SlideRenderingTest_Animations_DifferentKindOfTextBox.odp");
@@ -3477,60 +3817,107 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animati
     CPPUNIT_ASSERT_EQUAL(2000, nViewWidth);
     CPPUNIT_ASSERT_EQUAL(1500, nViewHeight);
 
-    std::vector<std::string> aHashes;
+    std::vector<std::string> aBufferHashes;
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
-        OUString rJsonMsg;
         double dScale = 1.0;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
 
         // Remember the hash of the buffer for uniqueness check
         auto aBufferHash = comphelper::Hash::calculateHash(pBuffer.data(), 
pBuffer.size(), comphelper::HashType::SHA1);
-        aHashes.push_back(comphelper::hashToString(aBufferHash));
+        aBufferHashes.push_back(comphelper::hashToString(aBufferHash));
 
-        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("Background"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
-        OUString rJsonMsg;
         double dScale = 1.0;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
 
         // Remember the hash of the buffer for uniqueness check
         auto aBufferHash = comphelper::Hash::calculateHash(pBuffer.data(), 
pBuffer.size(), comphelper::HashType::SHA1);
-        aHashes.push_back(comphelper::hashToString(aBufferHash));
+        aBufferHashes.push_back(comphelper::hashToString(aBufferHash));
+
+        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
 
-        debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(0, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChild.get_child("checksum").get_value<std::string>());
     }
 
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
-        OUString rJsonMsg;
         double dScale = 1.0;
-        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        
CPPUNIT_ASSERT(!pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
 
         // Remember the hash of the buffer for uniqueness check
         auto aBufferHash = comphelper::Hash::calculateHash(pBuffer.data(), 
pBuffer.size(), comphelper::HashType::SHA1);
-        aHashes.push_back(comphelper::hashToString(aBufferHash));
+        aBufferHashes.push_back(comphelper::hashToString(aBufferHash));
+
+        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
aJson.toUtf8().getStr());
+
+        boost::property_tree::ptree aTree;
+        readJSON(aTree, aJson);
+
+        CPPUNIT_ASSERT_EQUAL(std::string("DrawPage"), 
aTree.get_child("group").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(1, aTree.get_child("index").get_value<int>());
+        CPPUNIT_ASSERT_EQUAL(std::string("animated"), 
aTree.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "slideHash"));
+
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aTree, "content"));
+        auto aContentChild = aTree.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "hash"));
+        CPPUNIT_ASSERT_EQUAL(std::string("false"), 
aContentChild.get_child("initVisible").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("bitmap"), 
aContentChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "bounds"));
 
-        debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, 
rJsonMsg.toUtf8().getStr());
+        CPPUNIT_ASSERT_EQUAL(true, has_child(aContentChild, "content"));
+        auto aContentChildChild = aContentChild.get_child("content");
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGETYPE%"), 
aContentChildChild.get_child("type").get_value<std::string>());
+        CPPUNIT_ASSERT_EQUAL(std::string("%IMAGECHECKSUM%"), 
aContentChildChild.get_child("checksum").get_value<std::string>());
     }
 
     // check if all hashes are unique
-    CPPUNIT_ASSERT(is_unique(aHashes));
+    CPPUNIT_ASSERT(is_unique(aBufferHashes));
 
     // Check we are done
     {
         std::vector<sal_uInt8> pBuffer(nViewWidth * nViewHeight * 4);
         bool bIsBitmapLayer = false;
-        OUString rJsonMsg;
         double dScale = 1.0;
-        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, rJsonMsg));
+        OUString aJson;
+        CPPUNIT_ASSERT(pXImpressDocument->renderNextSlideLayer(pBuffer.data(), 
bIsBitmapLayer, dScale, aJson));
+        CPPUNIT_ASSERT(aJson.isEmpty());
     }
 
     pXImpressDocument->postSlideshowCleanup();

Reply via email to