drawinglayer/source/processor2d/baseprocessor2d.cxx | 3 drawinglayer/source/processor2d/vclpixelprocessor2d.cxx | 4 sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animations_DifferentKindOfTextBox.odp |binary sd/qa/unit/tiledrendering/tiledrendering.cxx | 86 ++++++++++ sd/source/ui/tools/SlideshowLayerRenderer.cxx | 25 +- 5 files changed, 104 insertions(+), 14 deletions(-)
New commits: commit cde8bf6bcf3b361bd107276efe14b2a221826399 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Wed Oct 16 09:30:11 2024 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Mar 12 18:30:54 2025 +0100 slideshow: fix para. rendering when using SdrBlockTextPrimitive2D If using an empty ViewInformation, it is possible that the prim. decomposition is redone, when a different ViewInformation is used. This removes all visibility flags for the paragraphs, so the whole text is rendered. This fixes the issue by using the same instance of the ViewInformation that is also used later for rendering the primitives to the VirtualDevice, so the buffered decomposition is used. Also a test is added - it checks the hash of the buffer, which should be different for all 3 layers. For this the tostring has to be moved to the common hash.hxx, so we can reuse it in out tests. Includes: Author: Marco Cecchetti <marco.cecche...@collabora.com> AuthorDate: Wed Mar 5 23:15:33 2025 +0100 slideshow: regression: layer with paragraph has not the expected content Change-Id: I850c6922cdd358eee35074fbff04f238994b2c76 Otherwise 'make -C sd -sr CppunitTest_sd_tiledrendering CPPUNIT_TEST_NAME=testSlideshowLayeredRendering_Animation_DifferentKindOfTextBox' would fail. Change-Id: I4c951215a52e302d3b7b60a30c1b995002e53a4b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182833 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/drawinglayer/source/processor2d/baseprocessor2d.cxx b/drawinglayer/source/processor2d/baseprocessor2d.cxx index 437faa3a5016..8209ca00f0fb 100644 --- a/drawinglayer/source/processor2d/baseprocessor2d.cxx +++ b/drawinglayer/source/processor2d/baseprocessor2d.cxx @@ -62,7 +62,8 @@ namespace drawinglayer::processor2d { for (const primitive2d::Primitive2DReference& rCandidate : rSource) { - if (rCandidate) + // Skip, if not visible + if (rCandidate && rCandidate->getVisible()) processBasePrimitive2D(*rCandidate); } } diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 98182a43a758..3264cdfc2a4a 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -192,10 +192,6 @@ bool VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect( void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { - // Skip, if not visible - if (!rCandidate.getVisible()) - return; - switch (rCandidate.getPrimitive2DID()) { case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D: diff --git a/sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animations_DifferentKindOfTextBox.odp b/sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animations_DifferentKindOfTextBox.odp new file mode 100644 index 000000000000..47777662805f Binary files /dev/null and b/sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animations_DifferentKindOfTextBox.odp differ diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx index 01d987433404..a6c3714a3b75 100644 --- a/sd/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx @@ -18,6 +18,7 @@ #include <comphelper/propertysequence.hxx> #include <comphelper/propertyvalue.hxx> #include <comphelper/string.hxx> +#include <comphelper/hash.hxx> #include <editeng/eeitem.hxx> #include <editeng/editids.hrc> #include <editeng/editobj.hxx> @@ -3422,6 +3423,91 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideshowLayeredRendering_Animati 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"); + pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + CPPUNIT_ASSERT(pViewShell); + SdPage* pPage = pViewShell->GetActualPage(); + CPPUNIT_ASSERT(pPage); + sal_Int32 nViewWidth = 2000; + sal_Int32 nViewHeight = 2000; + + std::string sHash = GetInterfaceHash(GetXDrawPageForSdrPage(pPage)); + CPPUNIT_ASSERT(pXImpressDocument->createSlideRenderer(sHash.c_str(), 0, nViewWidth, nViewHeight, true, true)); + CPPUNIT_ASSERT_EQUAL(2000, nViewWidth); + CPPUNIT_ASSERT_EQUAL(1500, nViewHeight); + + std::vector<std::string> aHashes; + + { + 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)); + + // 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)); + + debugWriteImageToFile(1, pBuffer, nViewWidth, nViewHeight, rJsonMsg.toUtf8().getStr()); + } + + { + 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)); + + // 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)); + + debugWriteImageToFile(2, pBuffer, nViewWidth, nViewHeight, rJsonMsg.toUtf8().getStr()); + } + + { + 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)); + + // 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)); + + debugWriteImageToFile(3, pBuffer, nViewWidth, nViewHeight, rJsonMsg.toUtf8().getStr()); + } + + // check if all hashes are unique + CPPUNIT_ASSERT(is_unique(aHashes)); + + // 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)); + } + + pXImpressDocument->postSlideshowCleanup(); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/tools/SlideshowLayerRenderer.cxx b/sd/source/ui/tools/SlideshowLayerRenderer.cxx index 143acfb5e668..3fb9160f6297 100644 --- a/sd/source/ui/tools/SlideshowLayerRenderer.cxx +++ b/sd/source/ui/tools/SlideshowLayerRenderer.cxx @@ -138,7 +138,8 @@ void changeBackground(drawinglayer::primitive2d::Primitive2DContainer const& rCo } drawinglayer::primitive2d::TextHierarchyBlockPrimitive2D* -findTextBlock(drawinglayer::primitive2d::Primitive2DContainer const& rContainer) +findTextBlock(drawinglayer::primitive2d::Primitive2DContainer const& rContainer, + drawinglayer::geometry::ViewInformation2D const& rViewInformation2D) { for (size_t i = 0; i < rContainer.size(); i++) { @@ -157,7 +158,8 @@ findTextBlock(drawinglayer::primitive2d::Primitive2DContainer const& rContainer) = dynamic_cast<drawinglayer::primitive2d::GroupPrimitive2D*>(pBasePrimitive); if (pGroupPrimitive) { - auto* pTextBlock = findTextBlock(pGroupPrimitive->getChildren()); + auto* pTextBlock + = findTextBlock(pGroupPrimitive->getChildren(), rViewInformation2D); if (pTextBlock) return pTextBlock; } @@ -169,9 +171,8 @@ findTextBlock(drawinglayer::primitive2d::Primitive2DContainer const& rContainer) { // try to decompose drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer; - pBasePrimitive->get2DDecomposition(aPrimitiveContainer, - drawinglayer::geometry::ViewInformation2D()); - auto* pTextBlock = findTextBlock(aPrimitiveContainer); + pBasePrimitive->get2DDecomposition(aPrimitiveContainer, rViewInformation2D); + auto* pTextBlock = findTextBlock(aPrimitiveContainer, rViewInformation2D); if (pTextBlock) return pTextBlock; } @@ -181,9 +182,10 @@ findTextBlock(drawinglayer::primitive2d::Primitive2DContainer const& rContainer) } void modifyParagraphs(drawinglayer::primitive2d::Primitive2DContainer& rContainer, + drawinglayer::geometry::ViewInformation2D const& rViewInformation2D, std::deque<sal_Int32> const& rPreserveIndices, bool bRenderObject) { - auto* pTextBlock = findTextBlock(rContainer); + auto* pTextBlock = findTextBlock(rContainer, rViewInformation2D); if (pTextBlock) { @@ -243,6 +245,10 @@ public: return; SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject(); + + drawinglayer::geometry::ViewInformation2D const& rViewInformation2D + = rOriginal.GetObjectContact().getViewInformation2D(); + // Check if we are rendering an object that is valid to render (exists, and not empty) if (pObject == nullptr || pObject->IsEmptyPresObj()) return; @@ -338,7 +344,8 @@ public: if (bRenderOtherParagraphs) { - modifyParagraphs(rContainer, nOtherParagraphs, true); // render the object + modifyParagraphs(rContainer, rViewInformation2D, nOtherParagraphs, + true); // render the object mrRenderState.mnCurrentTargetParagraph = -1; } else @@ -348,8 +355,8 @@ public: std::deque<sal_Int32> aPreserveParagraphs{ nParagraph }; mrRenderState.mnCurrentTargetParagraph = nParagraph; - modifyParagraphs(rContainer, aPreserveParagraphs, - false); // render only the paragraphs + // render only the paragraphs + modifyParagraphs(rContainer, rViewInformation2D, aPreserveParagraphs, false); } }