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.cecchetti@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 <vmiklos@collabora.com>
This commit is contained in:
committed by
Miklos Vajna
parent
3cf71eec36
commit
cde8bf6bcf
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
BIN
Binary file not shown.
@@ -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: */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user