oox/qa/unit/data/tdf170095.pptx |binary
 oox/qa/unit/shape.cxx           |   18 ++++++++++++++++++
 oox/source/drawingml/shape.cxx  |   17 +++++++++++++----
 svx/source/svdraw/svdobj.cxx    |   28 ++++++++++++++++++++++++++++
 4 files changed, 59 insertions(+), 4 deletions(-)

New commits:
commit 2f03d01039403885cc53170e4bdfe947da14e8f1
Author:     Jaume Pujantell <[email protected]>
AuthorDate: Tue Dec 23 09:26:12 2025 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Fri Jan 2 14:02:39 2026 +0100

    tdf#170095 override soft edge if there are 3D effects
    
    In OOXML, 3D effects override the soft-edge effect. Currently in LO 3D
    effects are not implemented, they are just remembered in a grabbag.
    
    To bring LO's behavior closer to other software, if when loaded there
    are both 3D effects and soft edge effect we ignore the soft edge effect.
    And if, while editing, a user adds soft edge effect then we dumb the
    remembered 3D effects in the grabbag.
    
    Change-Id: I2f59422d25c24bb4f9042694e0315bb15a2ac4c5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196151
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/oox/qa/unit/data/tdf170095.pptx b/oox/qa/unit/data/tdf170095.pptx
new file mode 100644
index 000000000000..65bf6535bb48
Binary files /dev/null and b/oox/qa/unit/data/tdf170095.pptx differ
diff --git a/oox/qa/unit/shape.cxx b/oox/qa/unit/shape.cxx
index 177b538d5fc6..a4cdcb6c6c4a 100644
--- a/oox/qa/unit/shape.cxx
+++ b/oox/qa/unit/shape.cxx
@@ -998,6 +998,24 @@ CPPUNIT_TEST_FIXTURE(OoxShapeTest, testGlowOnGroup)
     uno::Reference<container::XIndexAccess> xGroup(xDrawPage->getByIndex(0), 
uno::UNO_QUERY);
     CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xGroup->getCount());
 }
+
+CPPUNIT_TEST_FIXTURE(OoxShapeTest, testTdf170095SoftEdge3D)
+{
+    // Load file with a shape with both soft edge and 3D effects
+    loadFromFile(u"tdf170095.pptx");
+
+    // Then make sure the shape has no soft edge:
+    uno::Reference<drawing::XDrawPagesSupplier> 
xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPage> 
xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
+                                                 uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), 
uno::UNO_QUERY);
+    sal_Int32 nSoftEdgeRad{};
+    xShape->getPropertyValue(u"SoftEdgeRadius"_ustr) >>= nSoftEdgeRad;
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 0
+    // - Actual  : 882
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), nSoftEdgeRad);
+}
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 7afa155c976c..c05f7bf8d0e9 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -1618,6 +1618,18 @@ Reference< XShape > const & Shape::createAndInsert(
                 aShapeProps.setProperty(PROP_CharHeight, GetFontHeight( 
mpMasterTextListStyle->getListStyle()[0].getTextCharacterProperties().moHeight.value()
 ));
         }
 
+        Sequence<PropertyValue> aCamera3DEffects = 
get3DProperties().getCameraAttributes();
+        Sequence<PropertyValue> aLightRig3DEffects = 
get3DProperties().getLightRigAttributes();
+        Sequence<PropertyValue> aShape3DEffects
+            = get3DProperties().getShape3DAttributes(rGraphicHelper, 
nFillPhClr);
+        bool bHas3DProps = aCamera3DEffects.hasElements() || 
aLightRig3DEffects.hasElements()
+                           || aShape3DEffects.hasElements();
+        if (bHas3DProps)
+        {
+            // 3D properties override softeEdge
+            getEffectProperties().maSoftEdge.moRad = 0;
+        }
+
         // applying properties
         aShapeProps.assignUsed( getShapeProperties() );
         aShapeProps.assignUsed( maDefaultShapeProperties );
@@ -2011,10 +2023,7 @@ Reference< XShape > const & Shape::createAndInsert(
             }
 
             // add 3D effects if any to GrabBag. They are still used in export.
-            Sequence< PropertyValue > aCamera3DEffects = 
get3DProperties().getCameraAttributes();
-            Sequence< PropertyValue > aLightRig3DEffects = 
get3DProperties().getLightRigAttributes();
-            Sequence< PropertyValue > aShape3DEffects = 
get3DProperties().getShape3DAttributes( rGraphicHelper, nFillPhClr );
-            if( aCamera3DEffects.hasElements() || 
aLightRig3DEffects.hasElements() || aShape3DEffects.hasElements() )
+            if (bHas3DProps)
             {
                 uno::Sequence<beans::PropertyValue> a3DEffectsGrabBag = 
comphelper::InitPropertySequence(
                 {
diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx
index ea7571d4cc6c..c71961a7f88f 100644
--- a/svx/source/svdraw/svdobj.cxx
+++ b/svx/source/svdraw/svdobj.cxx
@@ -36,6 +36,7 @@
 #include <drawinglayer/processor2d/contourextractor2d.hxx>
 #include <drawinglayer/processor2d/linegeometryextractor2d.hxx>
 #include <comphelper/processfactory.hxx>
+#include <comphelper/sequence.hxx>
 #include <editeng/editeng.hxx>
 #include <editeng/outlobj.hxx>
 #include <o3tl/deleter.hxx>
@@ -2025,6 +2026,33 @@ const SfxPoolItem& SdrObject::GetMergedItem(const 
sal_uInt16 nWhich) const
 void SdrObject::SetMergedItemSetAndBroadcast(const SfxItemSet& rSet, bool 
bClearAllItems)
 {
     GetProperties().SetMergedItemSetAndBroadcast(rSet, bClearAllItems);
+
+    const SdrMetricItem* pItem;
+    const bool bSetSoftEdge
+        = (SfxItemState::SET == rSet.GetItemState(SDRATTR_SOFTEDGE_RADIUS, 
true, &pItem)
+           && pItem->GetValue() > 0);
+    if (bSetSoftEdge)
+    {
+        // Remove 3D grabbag
+        try
+        {
+            css::uno::Any aAnyGrabBag;
+            GetGrabBagItem(aAnyGrabBag);
+            uno::Sequence<beans::PropertyValue> aSeqGrabBag
+                = aAnyGrabBag.get<uno::Sequence<beans::PropertyValue>>();
+            auto it = std::find_if(aSeqGrabBag.begin(), aSeqGrabBag.end(),
+                                   [](const beans::PropertyValue& rProp) {
+                                       return rProp.Name == 
u"3DEffectProperties"_ustr;
+                                   });
+            if (it == aSeqGrabBag.end())
+                return;
+            comphelper::removeElementAt(aSeqGrabBag, it - aSeqGrabBag.begin());
+            SetGrabBagItem(css::uno::Any(aSeqGrabBag));
+        }
+        catch (...)
+        {
+        }
+    }
 }
 
 void SdrObject::ApplyNotPersistAttr(const SfxItemSet& rAttr)

Reply via email to