oox/qa/unit/data/Scene3d_cropped_image.pptx |binary
 oox/qa/unit/data/Scene3d_pureImage.pptx     |binary
 oox/qa/unit/testscene3d.cxx                 |   68 ++++++++++++++++++++++++++++
 oox/source/drawingml/scene3dhelper.cxx      |   20 +++++---
 oox/source/drawingml/shape.cxx              |    8 +--
 5 files changed, 85 insertions(+), 11 deletions(-)

New commits:
commit 15e43d9679773efcf869ff8272c7932b59fe1c68
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Fri Mar 22 10:43:48 2024 +0100
Commit:     Regina Henschel <rb.hensc...@t-online.de>
CommitDate: Sat Mar 23 10:20:25 2024 +0100

    tdf#70039 partly enable 3D-image from pptx
    
    This enables 3D for those images, that have been cropped to a shape.
    Those images are imported as custom shapes anyway and thus can use the
    now possible rendering as 3D-scene.
    
    The patch does not change the import of pure images with 3D properties.
    (Such is possible in OOXML.) Using a custom shape here too, would
    restrict the user. Exchange of the image or using color corrections
    and filters on the image, for example, would be no longer possible.
    
    It also fixes the error, that a z-rotation of a pure image was no
    longer considered.
    
    Change-Id: I626b1687c5aed1cac6f35388a3b25941673b5513
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165194
    Tested-by: Jenkins
    Reviewed-by: Regina Henschel <rb.hensc...@t-online.de>

diff --git a/oox/qa/unit/data/Scene3d_cropped_image.pptx 
b/oox/qa/unit/data/Scene3d_cropped_image.pptx
new file mode 100644
index 000000000000..d97a7afae42b
Binary files /dev/null and b/oox/qa/unit/data/Scene3d_cropped_image.pptx differ
diff --git a/oox/qa/unit/data/Scene3d_pureImage.pptx 
b/oox/qa/unit/data/Scene3d_pureImage.pptx
new file mode 100644
index 000000000000..463d4b886760
Binary files /dev/null and b/oox/qa/unit/data/Scene3d_pureImage.pptx differ
diff --git a/oox/qa/unit/testscene3d.cxx b/oox/qa/unit/testscene3d.cxx
index ee60eb24c614..4b6415424515 100644
--- a/oox/qa/unit/testscene3d.cxx
+++ b/oox/qa/unit/testscene3d.cxx
@@ -555,6 +555,74 @@ CPPUNIT_TEST_FIXTURE(TestScene3d, test_material_wireframe)
                 "shade-mode"_ostr, "draft");
 }
 
+CPPUNIT_TEST_FIXTURE(TestScene3d, test_cropped_image)
+{
+    // The file contains an image that has been cropped to shape in 
PowerPoint. The image is in 3D
+    // mode with perspective camera perspectiveContrastingRightFacing and 
perspective angle 120°. The
+    // extrusion is 76200 EMU deep with extrusion color #00B050. As a cropped 
image, it was imported
+    // in earlier LO versions as custom shape with bitmap fill, but without 
any 3D.
+    loadFromFile(u"Scene3d_cropped_image.pptx");
+    uno::Reference<drawing::XShape> xShape(getShape(0, 0)); // shape 0 on page 0
+
+    // Prepare property maps
+    uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
+    uno::Sequence<beans::PropertyValue> aGeoPropSeq;
+    xShapeProps->getPropertyValue(u"CustomShapeGeometry"_ustr) >>= aGeoPropSeq;
+    comphelper::SequenceAsHashMap aGeoPropMap(aGeoPropSeq);
+    uno::Sequence<beans::PropertyValue> aExtrusionSeq;
+    aGeoPropMap.getValue(u"Extrusion"_ustr) >>= aExtrusionSeq;
+    comphelper::SequenceAsHashMap aExtrusionPropMap(aExtrusionSeq);
+
+    // Check that extrusion is on and has the correct geometry.
+    bool bIsExtruded(false);
+    aExtrusionPropMap.getValue(u"Extrusion"_ustr) >>= bIsExtruded;
+    CPPUNIT_ASSERT_MESSAGE("error: Extrusion is disabled", bIsExtruded);
+
+    drawing::ProjectionMode eProjectionMode = drawing::ProjectionMode_PARALLEL;
+    aExtrusionPropMap.getValue(u"ProjectionMode"_ustr) >>= eProjectionMode;
+    CPPUNIT_ASSERT_EQUAL(drawing::ProjectionMode_PERSPECTIVE, eProjectionMode);
+
+    drawing::Position3D aViewPoint;
+    aExtrusionPropMap.getValue(u"ViewPoint"_ustr) >>= aViewPoint;
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aViewPoint.PositionX, 1E-12);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aViewPoint.PositionY, 1E-12);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(9223.7479, aViewPoint.PositionZ, 1E-5);
+
+    // Check shape rotation angles
+    drawing::EnhancedCustomShapeParameterPair aParaPair;
+    aExtrusionPropMap.getValue(UNO_NAME_MISC_OBJ_ROTATEANGLE) >>= aParaPair;
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(-6.94093344831102, 
aParaPair.First.Value.get<double>(), 1E-12);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(-44.4431265782766, 
aParaPair.Second.Value.get<double>(), 1E-12);
+    sal_Int32 nZRotate; // unit 1/100 degree
+    xShapeProps->getPropertyValue(UNO_NAME_MISC_OBJ_ROTATEANGLE) >>= nZRotate;
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(496), nZRotate);
+
+    // Check extrusion depth and color
+    aExtrusionPropMap.getValue(u"Depth"_ustr) >>= aParaPair;
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(212.0, aParaPair.First.Value.get<double>(), 
1E-12);
+    Color nColor;
+    xShapeProps->getPropertyValue(UNO_NAME_FILLCOLOR_2) >>= nColor;
+    CPPUNIT_ASSERT_EQUAL(Color(0x00b050), nColor);
+}
+
+CPPUNIT_TEST_FIXTURE(TestScene3d, test_pureImage)
+{
+    // Given a document with a scene3d element on an image. Because it would 
lose image properties
+    // it is currently (March 2024) not imported as custom shape. But the 
z-rotation is evaluated
+    // as users might have used this instead of shape rotation, for example.
+    loadFromFile(u"Scene3d_pureImage.pptx");
+    uno::Reference<drawing::XShape> xShape(getShape(0, 0)); // shape 0 on page 0
+
+    // Make sure it is an image.
+    CPPUNIT_ASSERT_EQUAL(u"com.sun.star.drawing.GraphicObjectShape"_ustr, 
xShape->getShapeType());
+
+    // Make sure the image is rotated.
+    uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
+    sal_Int32 nZRotate; // unit 1/100 degree
+    xShapeProps->getPropertyValue(UNO_NAME_MISC_OBJ_ROTATEANGLE) >>= nZRotate;
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(27000), nZRotate);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/scene3dhelper.cxx 
b/oox/source/drawingml/scene3dhelper.cxx
index acddea7643c4..ce8296050db6 100644
--- a/oox/source/drawingml/scene3dhelper.cxx
+++ b/oox/source/drawingml/scene3dhelper.cxx
@@ -398,6 +398,18 @@ bool Scene3DHelper::setExtrusionProperties(const 
oox::drawingml::Shape3DProperti
         return false; // error in document. OOXML specifies a fixed set of 
preset camera types.
     mnPrstCameraIndex = nPrstCameraIndex;
 
+    // Extrusion color is not handled as extrusion property but as shape 
property. Thus deliver it
+    // in any case, so that Shape::createAndInsert() knows about it.
+    rExtrusionColor = (*p3DProperties).maExtrusionColor;
+
+    // Even if we do not extrude an image, we still want to get the z-Rotation.
+    if (bBlockExtrusion)
+    {
+        rRotZ = 
basegfx::deg2rad<60000>((*p3DProperties).maCameraRotation.mnRevolution.value_or(0)
+                                        - rnMSOShapeRotation);
+        return false;
+    }
+
     // We use extrusion, if there is a rotation around x-axis or y-axis,
     // or if there is no such rotation but we have a perspective projection 
with true depth,
     // or we have a parallel projection other than a 'front' type.
@@ -413,18 +425,14 @@ bool Scene3DHelper::setExtrusionProperties(const 
oox::drawingml::Shape3DProperti
                             || (!bIsParallel && nDepthAmount > 0)
                             || (bIsParallel && !bIsParallelFrontType);
 
-    // Extrusion color is not handled as extrusion property but as shape 
property. Thus deliver it
-    // in any case, so that Shape::createAndInsert() knows about it.
-    rExtrusionColor = (*p3DProperties).maExtrusionColor;
-
-    if (!bCreateExtrusion || bBlockExtrusion)
+    if (!bCreateExtrusion)
         return false;
 
     // Create the extrusion properties in rPropertyMap so that they can be 
directly used.
     // Turn extrusion on
     rPropertyMap.setProperty(oox::PROP_Extrusion, true);
 
-    // Dummy value. Will be changed from evaluating the material properties, 
when implemented.
+    // Dummy value. Will be changed from evaluating the material properties.
     rPropertyMap.setProperty(oox::PROP_Diffusion, 100.0);
 
     // Camera properties
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 963391806c40..bd81fa9b42bf 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -975,11 +975,9 @@ Reference< XShape > const & Shape::createAndInsert(
     bool bIsCustomShape = (aServiceName == "com.sun.star.drawing.CustomShape" 
|| bIsCroppedGraphic);
     bool bIsConnectorShape = (aServiceName == 
"com.sun.star.drawing.ConnectorShape");
 
-    // Look for 3D. Its z-rotation and extrusion color become shape 
properties. Do it early as
-    // graphics might use 3D too and in that case should be imported as custom 
shape as well.
-    // FixMe. tdf#159515. We currently do not use extrusion, if an image has a 
3D-scene.
-    bool bBlockExtrusion = aServiceName == 
"com.sun.star.drawing.GraphicObjectShape" &&
-                           mp3DPropertiesPtr->mnPreset.has_value();
+    // Look for 3D. Its z-rotation and extrusion color become shape 
properties. We consider a
+    // z-rotation of an image even we currently do not extrude an image to 
3D-scene.
+    bool bBlockExtrusion = !bIsCustomShape && 
mp3DPropertiesPtr->mnPreset.has_value();
     double fShapeRotateInclCamera = 0.0; // unit rad; same orientation as 
shape property RotateAngle
     Color aExtrusionColor;
     Scene3DHelper aScene3DHelper;

Reply via email to