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;