oox/qa/unit/data/Scene3d_shape_rotation.pptx |binary
 oox/qa/unit/testscene3d.cxx                  |   12 +++++
 oox/source/export/drawingml.cxx              |   57 +++++++++++++++++++--------
 3 files changed, 54 insertions(+), 15 deletions(-)

New commits:
commit 207876cdcd7a4c19940d769a52d118751059dfe0
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Tue Mar 26 23:52:34 2024 +0100
Commit:     Regina Henschel <rb.hensc...@t-online.de>
CommitDate: Wed Mar 27 16:48:20 2024 +0100

    Restore shape rotation on roundtrip of pptx 3D shape
    
    As long as our support for extruded custom shapes from MS Office is
    rudimentary, we should restore the original values in case of saving
    to pptx.
    
    The patch uses the angle out of the interopGrabBag even if the user
    has changed the shape rotation. Considering a different angle would
    require to calculate camera, light rig and shape rotations. The effort
    for that is too large.
    
    Change-Id: Ib0549acc4ae13badd44fe9ae221a56ad21d28e1e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165359
    Tested-by: Jenkins
    Reviewed-by: Regina Henschel <rb.hensc...@t-online.de>

diff --git a/oox/qa/unit/data/Scene3d_shape_rotation.pptx 
b/oox/qa/unit/data/Scene3d_shape_rotation.pptx
new file mode 100644
index 000000000000..c8645e8a3780
Binary files /dev/null and b/oox/qa/unit/data/Scene3d_shape_rotation.pptx differ
diff --git a/oox/qa/unit/testscene3d.cxx b/oox/qa/unit/testscene3d.cxx
index 4b6415424515..fdad25be2cea 100644
--- a/oox/qa/unit/testscene3d.cxx
+++ b/oox/qa/unit/testscene3d.cxx
@@ -623,6 +623,18 @@ CPPUNIT_TEST_FIXTURE(TestScene3d, test_pureImage)
     CPPUNIT_ASSERT_EQUAL(sal_Int32(27000), nZRotate);
 }
 
+CPPUNIT_TEST_FIXTURE(TestScene3d, test_shape_rotation)
+{
+    // Given a document with a shape in 3D mode with shape rotation 
rot="300000".
+    loadFromFile(u"Scene3d_shape_rotation.pptx");
+    uno::Reference<drawing::XShape> xShape(getShape(0, 0));
+
+    // Make sure that the immediate export to pptx has the same shape rotation
+    save("Impress Office Open XML");
+    xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml");
+    assertXPath(pXmlDoc, "//p:spPr/a:xfrm"_ostr, "rot"_ostr, "300000");
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 20dba5b60de9..59b32eb2df4e 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2354,35 +2354,62 @@ void DrawingML::WriteShapeTransformation( const 
Reference< XShape >& rXShape, sa
             if (xPropertySet->getPropertyValue("RotateAngle") >>= nTmp)
                 nRotation = Degree100(nTmp);
         }
-        // tdf#133037: restore original rotate angle before output
-        if (nRotation && 
xPropertySetInfo->hasPropertyByName(UNO_NAME_MISC_OBJ_INTEROPGRABBAG))
+
+        // As long as the support of MS Office 3D-features is rudimentary, we 
restore the original
+        // values from InteropGrabBag. This affects images and custom shapes.
+        if 
(xPropertySetInfo->hasPropertyByName(UNO_NAME_MISC_OBJ_INTEROPGRABBAG))
         {
             uno::Sequence<beans::PropertyValue> aGrabBagProps;
             xPropertySet->getPropertyValue(UNO_NAME_MISC_OBJ_INTEROPGRABBAG) 
>>= aGrabBagProps;
-            auto p3DEffectProps = std::find_if(std::cbegin(aGrabBagProps), 
std::cend(aGrabBagProps),
+            auto p3DEffectProps = std::find_if(
+                std::cbegin(aGrabBagProps), std::cend(aGrabBagProps),
                 [](const PropertyValue& rProp) { return rProp.Name == 
"3DEffectProperties"; });
             if (p3DEffectProps != std::cend(aGrabBagProps))
             {
                 uno::Sequence<beans::PropertyValue> a3DEffectProps;
                 p3DEffectProps->Value >>= a3DEffectProps;
-                auto pCameraProps = std::find_if(std::cbegin(a3DEffectProps), 
std::cend(a3DEffectProps),
-                    [](const PropertyValue& rProp) { return rProp.Name == 
"Camera"; });
-                if (pCameraProps != std::cend(a3DEffectProps))
+                // We have imported a scene3d.
+                if (rXShape->getShapeType() == 
"com.sun.star.drawing.CustomShape")
+                {
+                    auto pMSORotation
+                        = std::find_if(std::cbegin(aGrabBagProps), 
std::cend(aGrabBagProps),
+                                       [](const PropertyValue& rProp) {
+                                           return rProp.Name == 
"mso-rotation-angle";
+                                       });
+                    sal_Int32 nMSORotation = 0;
+                    if (pMSORotation != std::cend(aGrabBagProps))
+                        pMSORotation->Value >>= nMSORotation;
+                    WriteTransformation(
+                        rXShape,
+                        tools::Rectangle(Point(aPos.X, aPos.Y), 
Size(aSize.Width, aSize.Height)),
+                        nXmlNamespace, bFlipHWrite, bFlipVWrite, nMSORotation);
+                    return;
+                }
+                if (rXShape->getShapeType() == 
"com.sun.star.drawing.GraphicObjectShape")
                 {
-                    uno::Sequence<beans::PropertyValue> aCameraProps;
-                    pCameraProps->Value >>= aCameraProps;
-                    auto pZRotationProp = 
std::find_if(std::cbegin(aCameraProps), std::cend(aCameraProps),
-                        [](const PropertyValue& rProp) { return rProp.Name == 
"rotRev"; });
-                    if (pZRotationProp != std::cend(aCameraProps))
+                    // tdf#133037: restore original rotate angle of image 
before output
+                    auto pCameraProps = std::find_if(
+                        std::cbegin(a3DEffectProps), std::cend(a3DEffectProps),
+                        [](const PropertyValue& rProp) { return rProp.Name == 
"Camera"; });
+                    if (pCameraProps != std::cend(a3DEffectProps))
                     {
-                        sal_Int32 nTmp = 0;
-                        pZRotationProp->Value >>= nTmp;
-                        nCameraRotation = NormAngle36000(Degree100(nTmp / 
-600));
+                        uno::Sequence<beans::PropertyValue> aCameraProps;
+                        pCameraProps->Value >>= aCameraProps;
+                        auto pZRotationProp = std::find_if(
+                            std::cbegin(aCameraProps), std::cend(aCameraProps),
+                            [](const PropertyValue& rProp) { return rProp.Name 
== "rotRev"; });
+                        if (pZRotationProp != std::cend(aCameraProps))
+                        {
+                            sal_Int32 nTmp = 0;
+                            pZRotationProp->Value >>= nTmp;
+                            nCameraRotation = NormAngle36000(Degree100(nTmp / 
-600));
+                            // FixMe tdf#160327. Vertical flip will be false.
+                        }
                     }
                 }
             }
         }
-    }
+    } // end if (!bSuppressRotation)
 
     // OOXML flips shapes before rotating them.
     if(bFlipH != bFlipV)

Reply via email to