From 264ec12d917fe7cda4ad52d38c50d31e8f0d3cff Mon Sep 17 00:00:00 2001 From: Marco Cecchetti Date: Thu, 28 Nov 2024 13:23:11 +0100 Subject: [PATCH] lok: slideshow: support effects applied to a group of shapes What has been achieved: - when a group is animated a layer with all shapes belonging to the group is created and marked as an animated layer - any effect applied to a shape belonging to a group (animated or not) is discarded - any effect based on color animations applied to a group of shapes is discarded For the last 2 points, we mimic the same behavior that occurs on LibreOffice. Unit tests for several scenarios as been provided. Change-Id: Ie094ac2a6a85f08e0e873062b0a780fe322c83bd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183448 Reviewed-by: Miklos Vajna Tested-by: Jenkins --- sd/CppunitTest_sd_tiledrendering.mk | 1 + .../SlideRenderingTest_Animated_Group.odp | Bin 0 -> 13643 bytes .../SlideRenderingTest_Animated_Groups.odp | Bin 0 -> 15162 bytes ...enderingTest_Animated_MultiLevel_Group.odp | Bin 0 -> 16715 bytes ...ringTest_Animated_Shape_Inside_A_Group.odp | Bin 0 -> 13425 bytes sd/qa/unit/tiledrendering/tiledrendering.cxx | 118 +++++++++++++++++- sd/source/ui/inc/SlideshowLayerRenderer.hxx | 19 +++ sd/source/ui/tools/SlideshowLayerRenderer.cxx | 81 +++++++++--- sd/source/ui/unoidl/unomodel.cxx | 105 +++++++++++++++- 9 files changed, 301 insertions(+), 23 deletions(-) create mode 100644 sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animated_Group.odp create mode 100644 sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animated_Groups.odp create mode 100644 sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animated_MultiLevel_Group.odp create mode 100644 sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animated_Shape_Inside_A_Group.odp diff --git a/sd/CppunitTest_sd_tiledrendering.mk b/sd/CppunitTest_sd_tiledrendering.mk index f1a0ad96f146..ec0d2e10c58d 100644 --- a/sd/CppunitTest_sd_tiledrendering.mk +++ b/sd/CppunitTest_sd_tiledrendering.mk @@ -40,6 +40,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sd_tiledrendering, \ $(eval $(call gb_CppunitTest_use_externals,sd_tiledrendering,\ boost_headers \ + frozen \ libxml2 \ )) diff --git a/sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animated_Group.odp b/sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animated_Group.odp new file mode 100644 index 0000000000000000000000000000000000000000..8be4426d207bd1cfd8ccbe4f2ebd1f6fa60ac0e7 GIT binary patch literal 13643 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 Uo7xNjAiX7;H}f(K)31O34H{{BegFUf literal 0 HcmV?d00001 diff --git a/sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animated_Groups.odp b/sd/qa/unit/tiledrendering/data/SlideRenderingTest_Animated_Groups.odp new file mode 100644 index 0000000000000000000000000000000000000000..73191f3901c20b8b92eaf400da19fe83a5c8895c GIT binary patch literal 15162 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 literal 0 HcmV?d00001 diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx index 69225bba363d..d663cd259b44 100644 --- a/sd/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx @@ -2955,7 +2955,7 @@ public: } } - void checkPageLayer(int nIndex, const std::string& rGroup) + void checkPageLayer(int nIndex, const std::string& rGroup, bool bIsAnimated = false) { const std::string sMsg = rGroup + " Layer Index: " + std::to_string(nIndex); @@ -2976,9 +2976,34 @@ public: CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, rGroup, aTree.get_child("group").get_value()); CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, nIndex, aTree.get_child("index").get_value()); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, std::string("bitmap"), - aTree.get_child("type").get_value()); - CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, true, has_child(aTree, "content")); + + if (!bIsAnimated) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, std::string("bitmap"), + aTree.get_child("type").get_value()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, true, has_child(aTree, "content")); + } + else + { + CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, std::string("animated"), + aTree.get_child("type").get_value()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, true, has_child(aTree, "content")); + + auto aContentChild = aTree.get_child("content"); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, true, has_child(aContentChild, "hash")); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, true, has_child(aContentChild, "initVisible")); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, std::string("bitmap"), + aContentChild.get_child("type").get_value()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg, true, has_child(aContentChild, "content")); + + auto aContentChildChild = aContentChild.get_child("content"); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + sMsg, std::string("%IMAGETYPE%"), + aContentChildChild.get_child("type").get_value()); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + sMsg, std::string("%IMAGECHECKSUM%"), + aContentChildChild.get_child("checksum").get_value()); + } } void checkFinalEmptyLayer() @@ -3409,6 +3434,91 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideshowLayeredRendering_Skip_Ba pXImpressDocument->postSlideshowCleanup(); } +CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideshowLayeredRendering_Animated_Shape_Inside_A_Group) +{ + // 1 not animated groups made up by 2 shapes + // one of the 2 shapes is animated + + SdXImpressDocument* pXImpressDocument + = createDoc("SlideRenderingTest_Animated_Shape_Inside_A_Group.odp"); + pXImpressDocument->initializeForTiledRendering(uno::Sequence()); + SlideRendererChecker aSlideRendererChecker(pXImpressDocument, 0, 2000, 2000, false, false); + aSlideRendererChecker.checkSlideSize(2000, 1125); + + // not animated group, no layer should be created for the animated shape + aSlideRendererChecker.checkPageLayer(0, "DrawPage", /*bIsAnimated=*/ false); + + aSlideRendererChecker.checkFinalEmptyLayer(); + + pXImpressDocument->postSlideshowCleanup(); +} + +CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideshowLayeredRendering_Animated_Group) +{ + // 1 animated groups made up by 2 not animated shapes + // a single not animated shape + + SdXImpressDocument* pXImpressDocument = createDoc("SlideRenderingTest_Animated_Group.odp"); + pXImpressDocument->initializeForTiledRendering(uno::Sequence()); + SlideRendererChecker aSlideRendererChecker(pXImpressDocument, 0, 2000, 2000, false, false); + aSlideRendererChecker.checkSlideSize(2000, 1125); + + // animated group + aSlideRendererChecker.checkPageLayer(0, "DrawPage", /*bIsAnimated=*/ true); + + // not animated shape + aSlideRendererChecker.checkPageLayer(1, "DrawPage", /*bIsAnimated=*/ false); + + aSlideRendererChecker.checkFinalEmptyLayer(); + + pXImpressDocument->postSlideshowCleanup(); +} + +CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideshowLayeredRendering_Animated_Groups) +{ + // 2 animated groups made up by 2 shapes each + + SdXImpressDocument* pXImpressDocument = createDoc("SlideRenderingTest_Animated_Groups.odp"); + pXImpressDocument->initializeForTiledRendering(uno::Sequence()); + SlideRendererChecker aSlideRendererChecker(pXImpressDocument, 0, 2000, 2000, false, false); + aSlideRendererChecker.checkSlideSize(2000, 1125); + + // 1st group + aSlideRendererChecker.checkPageLayer(0, "DrawPage", /*bIsAnimated=*/ true); + + // 2nd group + aSlideRendererChecker.checkPageLayer(1, "DrawPage", /*bIsAnimated=*/ true); + + aSlideRendererChecker.checkFinalEmptyLayer(); + + pXImpressDocument->postSlideshowCleanup(); +} + +CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideshowLayeredRendering_Animated_MultiLevel_Group) +{ + // 3 1st level groups made up by 2 shapes each + // the 1st group is not animated but one of its shape is + // the 2nd group is animated, none of its shapes is + // the 3rd group is animated with a color based effect + // 1st and 2nd group are grouped together and the 2nd level group is animated + + SdXImpressDocument* pXImpressDocument = createDoc("SlideRenderingTest_Animated_MultiLevel_Group.odp"); + pXImpressDocument->initializeForTiledRendering(uno::Sequence()); + SlideRendererChecker aSlideRendererChecker(pXImpressDocument, 0, 2000, 2000, false, false); + aSlideRendererChecker.checkSlideSize(2000, 1125); + + // a single layer should be created for the highest level group, + // embedded animated groups or animated shapes should be ignored + aSlideRendererChecker.checkPageLayer(0, "DrawPage", /*bIsAnimated=*/ true); + + // a group with applied an effect based on color animations should not be animated + aSlideRendererChecker.checkPageLayer(1, "DrawPage", /*bIsAnimated=*/ false); + + aSlideRendererChecker.checkFinalEmptyLayer(); + + pXImpressDocument->postSlideshowCleanup(); +} + CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideshowLayeredRendering_Animations) { // Check rendering of animated objects - each in own layer diff --git a/sd/source/ui/inc/SlideshowLayerRenderer.hxx b/sd/source/ui/inc/SlideshowLayerRenderer.hxx index 42794e0e6c6f..7f8f43fe3abb 100644 --- a/sd/source/ui/inc/SlideshowLayerRenderer.hxx +++ b/sd/source/ui/inc/SlideshowLayerRenderer.hxx @@ -24,6 +24,10 @@ #include #include +#include +#include +#include + class SdrPage; class SdrModel; class SdrObject; @@ -41,6 +45,21 @@ class ViewObjectContactRedirector; namespace sd { +constexpr auto constNonValidEffectsForGroupSet = frozen::make_unordered_set({ + "ooo-emphasis-fill-color", + "ooo-emphasis-font-color", + "ooo-emphasis-line-color", + "ooo-emphasis-color-blend", + "ooo-emphasis-complementary-color", + "ooo-emphasis-complementary-color-2", + "ooo-emphasis-contrasting-color", + "ooo-emphasis-darken", + "ooo-emphasis-desaturate", + "ooo-emphasis-flash-bulb", + "ooo-emphasis-lighten", + "ooo-emphasis-grow-with-color", +}); + class RenderContext; enum class RenderStage diff --git a/sd/source/ui/tools/SlideshowLayerRenderer.cxx b/sd/source/ui/tools/SlideshowLayerRenderer.cxx index bae2821fbefe..328859b202bb 100644 --- a/sd/source/ui/tools/SlideshowLayerRenderer.cxx +++ b/sd/source/ui/tools/SlideshowLayerRenderer.cxx @@ -150,6 +150,8 @@ OUString getMasterTextFieldType(SdrObject* pObject) return aType; } +bool isGroup(SdrObject* pObject) { return pObject->getChildrenOfSdrObject() != nullptr; } + /// Sets visible for all kinds of polypolys in the container void changePolyPolys(drawinglayer::primitive2d::Primitive2DContainer& rContainer, bool bRenderObject) @@ -298,6 +300,18 @@ private: || (mrRenderState.mbDateTimeEnabled && svType == u"DateTime"); } + SdrObject* getAnimatedAncestor(SdrObject* pObject) const + { + SdrObject* pAncestor = pObject; + while ((pAncestor = pAncestor->getParentSdrObjectFromSdrObject())) + { + auto aIterator = mrRenderState.maAnimationRenderInfoList.find(pAncestor); + if (aIterator != mrRenderState.maAnimationRenderInfoList.end()) + return pAncestor; + } + return pAncestor; + } + public: AnalyzeRenderingRedirector(RenderState& rRenderState, bool bRenderMasterPage) : mrRenderState(rRenderState) @@ -456,9 +470,26 @@ public: closeRenderPass(); } } + // check if object is part of an animated group + else if (SdrObject* pAncestor = getAnimatedAncestor(pObject)) + { + // a new animated group is started ? + if (mpCurrentRenderPass->mpObject && mpCurrentRenderPass->mpObject != pAncestor) + closeRenderPass(); + + // Add the animated object + mpCurrentRenderPass->maObjectsAndParagraphs.emplace(pObject, std::deque()); + mpCurrentRenderPass->meStage = eCurrentStage; + mpCurrentRenderPass->mbAnimation = true; + mpCurrentRenderPass->mpObject = pAncestor; + } // No special handling is needed, just add the object to the current rendering pass else { + // an animated group is complete ? + if (mpCurrentRenderPass->mpObject) + closeRenderPass(); + mpCurrentRenderPass->maObjectsAndParagraphs.emplace(pObject, std::deque()); mpCurrentRenderPass->meStage = eCurrentStage; } @@ -564,6 +595,20 @@ void SlideshowLayerRenderer::resolveEffect(CustomAnimationEffectPtr const& rEffe if (!pObject) return; + // afaics, when a shape is part of a group any applied effect is ignored, + // so no layer should be created + if (pObject->getParentSdrObjectFromSdrObject()) + return; + + // some kind of effect, like the ones based on color animations, + // is ignored when applied to a group + if (isGroup(pObject)) + { + if (constNonValidEffectsForGroupSet.find(rEffect->getPresetId().toUtf8()) + != constNonValidEffectsForGroupSet.end()) + return; + } + AnimationRenderInfo aAnimationInfo; auto aIterator = maRenderState.maAnimationRenderInfoList.find(pObject); if (aIterator != maRenderState.maAnimationRenderInfoList.end()) @@ -778,27 +823,33 @@ void writeAnimated(::tools::JsonWriter& aJsonWriter, AnimationLayerInfo const& r writeContentNode(aJsonWriter); writeBoundingBox(aJsonWriter, pObject); - if (nParagraph < 0) + // a group of object has no such property + if (!isGroup(pObject)) { - drawing::FillStyle aFillStyle - = pObject->GetProperties().GetItem(XATTR_FILLSTYLE).GetValue(); - if (aFillStyle == drawing::FillStyle::FillStyle_SOLID) + if (nParagraph < 0) { - auto aFillColor = pObject->GetProperties().GetItem(XATTR_FILLCOLOR).GetColorValue(); - aJsonWriter.put("fillColor", "#" + aFillColor.AsRGBHEXString()); + drawing::FillStyle aFillStyle + = pObject->GetProperties().GetItem(XATTR_FILLSTYLE).GetValue(); + if (aFillStyle == drawing::FillStyle::FillStyle_SOLID) + { + auto aFillColor + = pObject->GetProperties().GetItem(XATTR_FILLCOLOR).GetColorValue(); + aJsonWriter.put("fillColor", "#" + aFillColor.AsRGBHEXString()); + } + drawing::LineStyle aLineStyle + = pObject->GetProperties().GetItem(XATTR_LINESTYLE).GetValue(); + if (aLineStyle == drawing::LineStyle::LineStyle_SOLID) + { + auto aLineColor + = pObject->GetProperties().GetItem(XATTR_LINECOLOR).GetColorValue(); + aJsonWriter.put("lineColor", "#" + aLineColor.AsRGBHEXString()); + } } - drawing::LineStyle aLineStyle - = pObject->GetProperties().GetItem(XATTR_LINESTYLE).GetValue(); - if (aLineStyle == drawing::LineStyle::LineStyle_SOLID) + else { - auto aLineColor = pObject->GetProperties().GetItem(XATTR_LINECOLOR).GetColorValue(); - aJsonWriter.put("lineColor", "#" + aLineColor.AsRGBHEXString()); + writeFontColor(aJsonWriter, pObject, nParagraph); } } - else - { - writeFontColor(aJsonWriter, pObject, nParagraph); - } } } diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index 1fc8039f06fa..35c6da2b6140 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -718,6 +718,99 @@ bool isValidNode(const Reference& xNode) return false; } +SdrObject* getObjectForShape(uno::Reference const& xShape) +{ + if (!xShape.is()) + return nullptr; + SvxShape* pShape = comphelper::getFromUnoTunnel(xShape); + if (pShape) + return pShape->GetSdrObject(); + return nullptr; +} + +SdrObject* getTargetObject(const uno::Any& aTargetAny) +{ + SdrObject* pObject = nullptr; + uno::Reference xShape; + + if ((aTargetAny >>= xShape) && xShape.is()) + { + pObject = getObjectForShape(xShape); + } + else // if target is not a shape - could be paragraph target containing a shape + { + presentation::ParagraphTarget aParagraphTarget; + if ((aTargetAny >>= aParagraphTarget) && aParagraphTarget.Shape.is()) + { + pObject = getObjectForShape(aParagraphTarget.Shape); + } + } + + return pObject; +} + +bool isNodeTargetInShapeGroup(const Reference& xNode) +{ + Reference xAnimate(xNode, UNO_QUERY); + if (xAnimate.is()) + { + SdrObject* pObject = getTargetObject(xAnimate->getTarget()); + if (pObject) + return pObject->getParentSdrObjectFromSdrObject() != nullptr; + } + return false; +} + +bool isNodeTargetAGroup(const Reference& xNode) +{ + Reference xAnimate(xNode, UNO_QUERY); + if (xAnimate.is()) + { + SdrObject* pObject = getTargetObject(xAnimate->getTarget()); + if (pObject) + return pObject->getChildrenOfSdrObject() != nullptr; + } + return false; +} + +bool isEffectValidForTarget(const Reference& xNode) +{ + const Sequence aUserData(xNode->getUserData()); + for (const auto& rValue : aUserData) + { + if (!IsXMLToken(rValue.Name, XML_PRESET_ID)) + continue; + + OUString aPresetId; + if (rValue.Value >>= aPresetId) + { + if (constNonValidEffectsForGroupSet.find(aPresetId.toUtf8()) + != constNonValidEffectsForGroupSet.end()) + { + // it's in the list, so we need to check if the effect target is a group or not + Reference xContainer(xNode, UNO_QUERY); + if (xContainer.is()) + { + Reference xEnumerationAccess(xContainer, UNO_QUERY); + Reference xEnumeration = xEnumerationAccess->createEnumeration(); + + // target is the same for all children, check the first one + if (xEnumeration.is() && xEnumeration->hasMoreElements()) + { + Reference xChildNode(xEnumeration->nextElement(), + UNO_QUERY); + if (isNodeTargetAGroup(xChildNode)) + return false; + } + } + } + } + // preset id found and checked, we can exit + break; + } + return true; +} + void AnimationsExporter::exportAnimations() { if (!mxDrawPage.is() || !mxPageProps.is() || !mxRootNode.is() || !hasEffects()) @@ -729,12 +822,16 @@ void AnimationsExporter::exportAnimations() exportNodeImpl(mxRootNode); } } + void AnimationsExporter::exportNode(const Reference& xNode) { - if (!isValidNode(xNode)) - return; - auto aStruct = mrWriter.startStruct(); - exportNodeImpl(xNode); + // afaics, when a shape is part of a group any applied effect is ignored + // moreover, some kind of effect, like the ones based on color animations, + // is ignored when applied to a group + if (!isValidNode(xNode) || isNodeTargetInShapeGroup(xNode) || !isEffectValidForTarget(xNode)) + return; + auto aStruct = mrWriter.startStruct(); + exportNodeImpl(xNode); } void AnimationsExporter::exportNodeImpl(const Reference& xNode)