summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--oox/inc/drawingml/scene3dhelper.hxx13
-rw-r--r--oox/qa/unit/data/Scene3d_material_highlight.pptxbin0 -> 19845 bytes
-rw-r--r--oox/qa/unit/data/Scene3d_material_wireframe.pptxbin0 -> 15288 bytes
-rw-r--r--oox/qa/unit/testscene3d.cxx168
-rw-r--r--oox/source/drawingml/scene3dhelper.cxx93
-rw-r--r--oox/source/drawingml/shape.cxx4
6 files changed, 223 insertions, 55 deletions
diff --git a/oox/inc/drawingml/scene3dhelper.hxx b/oox/inc/drawingml/scene3dhelper.hxx
index af72a0e0cf2a..0f79825b13ca 100644
--- a/oox/inc/drawingml/scene3dhelper.hxx
+++ b/oox/inc/drawingml/scene3dhelper.hxx
@@ -50,6 +50,19 @@ public:
void setLightingProperties(const oox::drawingml::Shape3DPropertiesPtr p3DProperties,
const double& rRotZ, oox::PropertyMap& rPropertyMap);
+ /** Puts the material properties of the 3D-shape into the property map
+ @details OOXML and MSO describe the material properties using Specular Color (RGBA), Diffuse
+ Color (RGBA), Ambient Color (RGBA), Emissive Color (RGBA), Specular Power (positive int),
+ Diffuse Fresnel (int), Alpha Fresnel (int), Metal (bool) and Blinn Highlight (bool). ODF
+ and API have Diffusion (double), Specularity (double), Shininess (double), Metal (bool),
+ MetalType (enum). Thus a directly use of the MSO values is not possible and some material
+ types cannot be rendered. The method uses workarounds and approximations.
+ @param [in] p3DProperties contains besides other properties the material preset name
+ @param [in, out] rPropertyMap has properties directly usable in
+ CustomShapeProperties.pushToPropSet() for property Extrusion.*/
+ static void setMaterialProperties(const oox::drawingml::Shape3DPropertiesPtr p3DProperties,
+ oox::PropertyMap& rPropertyMap);
+
private:
/** Calculates angles suitable for API from OOXML scene3d angles.
@param [in] nLat, nLon, nRev in unit 1/60000 deg with same orientation as the attributes lat,
diff --git a/oox/qa/unit/data/Scene3d_material_highlight.pptx b/oox/qa/unit/data/Scene3d_material_highlight.pptx
new file mode 100644
index 000000000000..c299c21bc68c
--- /dev/null
+++ b/oox/qa/unit/data/Scene3d_material_highlight.pptx
Binary files differ
diff --git a/oox/qa/unit/data/Scene3d_material_wireframe.pptx b/oox/qa/unit/data/Scene3d_material_wireframe.pptx
new file mode 100644
index 000000000000..f72baeb25178
--- /dev/null
+++ b/oox/qa/unit/data/Scene3d_material_wireframe.pptx
Binary files differ
diff --git a/oox/qa/unit/testscene3d.cxx b/oox/qa/unit/testscene3d.cxx
index 5ca452ea3d21..48b968ba23cd 100644
--- a/oox/qa/unit/testscene3d.cxx
+++ b/oox/qa/unit/testscene3d.cxx
@@ -43,7 +43,7 @@ protected:
uno::Reference<drawing::XShape> getShape(sal_uInt8 nShapeIndex, sal_uInt8 nPageIndex);
// Converts the shape 0 on page 0 to a bitmap and returns this bitmap.
// It assumes, that shape 0 on page 0 is the only shape.
- void getShapeAsBitmap(BitmapEx& rBMP);
+ void getShapeAsBitmap(BitmapEx& rBMP, sal_uInt8 nShapeIndex);
};
uno::Reference<drawing::XShape> TestScene3d::getShape(sal_uInt8 nShapeIndex, sal_uInt8 nPageIndex)
@@ -60,20 +60,20 @@ uno::Reference<drawing::XShape> TestScene3d::getShape(sal_uInt8 nShapeIndex, sal
return xShape;
}
-void TestScene3d::getShapeAsBitmap(BitmapEx& rBMP)
+void TestScene3d::getShapeAsBitmap(BitmapEx& rBMP, sal_uInt8 nShapeIndex)
{
SfxViewShell* pViewShell = SfxViewShell::Current();
SdrView* pSdrView = pViewShell->GetDrawView();
// Mark object and convert it to bitmap
- uno::Reference<drawing::XShape> xShape3D(getShape(0, 0));
+ uno::Reference<drawing::XShape> xShape3D(getShape(nShapeIndex, 0));
SdrObject* pSdrShape(SdrObject::getSdrObjectFromXShape(xShape3D));
pSdrView->MarkObj(pSdrShape, pSdrView->GetSdrPageView());
dispatchCommand(mxComponent, ".uno:ConvertIntoBitmap", {});
pSdrView->UnmarkAll();
// Get graphic
- uno::Reference<drawing::XShape> xShapeBmp(getShape(0, 0));
+ uno::Reference<drawing::XShape> xShapeBmp(getShape(nShapeIndex, 0));
SdrGrafObj* pGrafObj = dynamic_cast<SdrGrafObj*>(SdrObject::getSdrObjectFromXShape(xShapeBmp));
CPPUNIT_ASSERT_MESSAGE("No image object created", pGrafObj);
const Graphic& rGraphic = pGrafObj->GetGraphic();
@@ -81,6 +81,28 @@ void TestScene3d::getShapeAsBitmap(BitmapEx& rBMP)
CPPUNIT_ASSERT_MESSAGE("No bitmap", !rBMP.IsEmpty());
}
+namespace
+{
+void lcl_AssertColorsApproximateEqual(const ::Color& aExpected, const ::Color& aActual)
+{
+ // Currently (March 2024), the import of lighting and material is only approximately possible.
+ // Thus colors are not identical. When the import will be improved, the tolerances should be
+ // reduced. The test uses HSB instead of RGB, because differences in hue are more irritating and
+ // should be detected as a priority. That is not possible with GetColorError() method.
+ sal_uInt16 nExpH;
+ sal_uInt16 nExpS;
+ sal_uInt16 nExpB;
+ sal_uInt16 nActH;
+ sal_uInt16 nActS;
+ sal_uInt16 nActB;
+ aExpected.RGBtoHSB(nExpH, nExpS, nExpB);
+ aActual.RGBtoHSB(nActH, nActS, nActB);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Hue", nExpH, nActH, 2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Saturation", nExpS, nActS, 13);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Brightness", nExpB, nActB, 11);
+}
+} // end anonymous namespace
+
CPPUNIT_TEST_FIXTURE(TestScene3d, test_isometricRightUp)
{
// Given a document with a scene3d element on a shape. Without the fix, the shape was imported as
@@ -357,21 +379,17 @@ CPPUNIT_TEST_FIXTURE(TestScene3d, test_lightRig_modernCamera)
// The test assumes rendering with ShadeMode_FLAT.
loadFromFile(u"Scene3d_lightRig_modernCamera.pptx");
BitmapEx aBMP;
- getShapeAsBitmap(aBMP);
+ getShapeAsBitmap(aBMP, 0);
// Size in pixel depends on dpi. Thus calculate positions relative to size.
// Color in center
sal_Int32 nX = 0.5 * aBMP.GetSizePixel().Width();
sal_Int32 nY = 0.5 * aBMP.GetSizePixel().Height();
- ::Color aExpectedCenter(248, 226, 212);
- CPPUNIT_ASSERT_MESSAGE("center color wrong",
- aExpectedCenter.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
+ lcl_AssertColorsApproximateEqual(::Color(247, 225, 211), aBMP.GetPixelColor(nX, nY));
// Color left
nX = 0.046122 * aBMP.GetSizePixel().Width();
nY = 0.5 * aBMP.GetSizePixel().Height();
- ::Color aExpectedLeft(0, 105, 48);
- CPPUNIT_ASSERT_MESSAGE("left color wrong",
- aExpectedLeft.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
+ lcl_AssertColorsApproximateEqual(::Color(0, 103, 47), aBMP.GetPixelColor(nX, nY));
}
CPPUNIT_TEST_FIXTURE(TestScene3d, test_lightRig_legacyCamera)
@@ -383,21 +401,17 @@ CPPUNIT_TEST_FIXTURE(TestScene3d, test_lightRig_legacyCamera)
// The test assumes rendering with ShadeMode_FLAT.
loadFromFile(u"Scene3d_lightRig_legacyCamera.pptx");
BitmapEx aBMP;
- getShapeAsBitmap(aBMP);
+ getShapeAsBitmap(aBMP, 0);
// Size in pixel depends on dpi. Thus calculate positions relative to size.
// Color in center
sal_Int32 nX = 0.5 * aBMP.GetSizePixel().Width();
sal_Int32 nY = 0.5 * aBMP.GetSizePixel().Height();
- ::Color aExpectedCenter(96, 88, 82);
- CPPUNIT_ASSERT_MESSAGE("center color wrong",
- aExpectedCenter.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
+ lcl_AssertColorsApproximateEqual(::Color(94, 86, 80), aBMP.GetPixelColor(nX, nY));
// Color left
nX = 0.046122 * aBMP.GetSizePixel().Width();
nY = 0.5 * aBMP.GetSizePixel().Height();
- ::Color aExpectedLeft(0, 180, 82);
- CPPUNIT_ASSERT_MESSAGE("left color wrong",
- aExpectedLeft.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
+ lcl_AssertColorsApproximateEqual(::Color(5, 185, 87), aBMP.GetPixelColor(nX, nY));
}
CPPUNIT_TEST_FIXTURE(TestScene3d, test_lightRig_default)
@@ -408,27 +422,21 @@ CPPUNIT_TEST_FIXTURE(TestScene3d, test_lightRig_default)
// The test assumes rendering with ShadeMode_FLAT.
loadFromFile(u"Scene3d_lightRig_default.pptx");
BitmapEx aBMP;
- getShapeAsBitmap(aBMP);
+ getShapeAsBitmap(aBMP, 0);
// Size in pixel depends on dpi. Thus calculate positions relative to size.
// Front color
sal_Int32 nX = 0.93811 * aBMP.GetSizePixel().Width();
sal_Int32 nY = 0.49904 * aBMP.GetSizePixel().Height();
- ::Color aExpectedFront(165, 187, 150);
- CPPUNIT_ASSERT_MESSAGE("front color wrong",
- aExpectedFront.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
+ lcl_AssertColorsApproximateEqual(::Color(165, 187, 150), aBMP.GetPixelColor(nX, nY));
// Left color
nX = 0.078176 * aBMP.GetSizePixel().Width();
nY = 0.49904 * aBMP.GetSizePixel().Height();
- ::Color aExpectedLeft(255, 189, 74);
- CPPUNIT_ASSERT_MESSAGE("left color wrong",
- aExpectedLeft.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
+ lcl_AssertColorsApproximateEqual(::Color(255, 189, 74), aBMP.GetPixelColor(nX, nY));
// Top color
nX = 0.48860 * aBMP.GetSizePixel().Width();
nY = 0.069098 * aBMP.GetSizePixel().Height();
- ::Color aExpectedTop(189, 100, 39);
- CPPUNIT_ASSERT_MESSAGE("top color wrong",
- aExpectedTop.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
+ lcl_AssertColorsApproximateEqual(::Color(189, 100, 39), aBMP.GetPixelColor(nX, nY));
}
CPPUNIT_TEST_FIXTURE(TestScene3d, test_lightRig_dir_rotation)
@@ -439,27 +447,21 @@ CPPUNIT_TEST_FIXTURE(TestScene3d, test_lightRig_dir_rotation)
// and MSO. The test assumes rendering with ShadeMode_FLAT.
loadFromFile(u"Scene3d_lightRig_dir_rotation.pptx");
BitmapEx aBMP;
- getShapeAsBitmap(aBMP);
+ getShapeAsBitmap(aBMP, 0);
// Size in pixel depends on dpi. Thus calculate positions relative to size.
// Front color
sal_Int32 nX = 0.93811 * aBMP.GetSizePixel().Width();
sal_Int32 nY = 0.49904 * aBMP.GetSizePixel().Height();
- ::Color aExpectedFront(165, 187, 150);
- CPPUNIT_ASSERT_MESSAGE("front color wrong",
- aExpectedFront.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
+ lcl_AssertColorsApproximateEqual(::Color(165, 187, 150), aBMP.GetPixelColor(nX, nY));
// Left color
nX = 0.078176 * aBMP.GetSizePixel().Width();
nY = 0.49904 * aBMP.GetSizePixel().Height();
- ::Color aExpectedLeft(206, 108, 42);
- CPPUNIT_ASSERT_MESSAGE("left color wrong",
- aExpectedLeft.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
+ lcl_AssertColorsApproximateEqual(::Color(206, 108, 42), aBMP.GetPixelColor(nX, nY));
// Top color
nX = 0.48860 * aBMP.GetSizePixel().Width();
nY = 0.069098 * aBMP.GetSizePixel().Height();
- ::Color aExpectedTop(255, 189, 74);
- CPPUNIT_ASSERT_MESSAGE("top color wrong",
- aExpectedTop.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
+ lcl_AssertColorsApproximateEqual(::Color(255, 189, 74), aBMP.GetPixelColor(nX, nY));
}
CPPUNIT_TEST_FIXTURE(TestScene3d, test_lightRig_rot_rotation)
@@ -469,32 +471,88 @@ CPPUNIT_TEST_FIXTURE(TestScene3d, test_lightRig_rot_rotation)
// The test assumes rendering with ShadeMode_FLAT.
loadFromFile(u"Scene3d_lightRig_rot_rotation.pptx");
BitmapEx aBMP;
- getShapeAsBitmap(aBMP);
+ getShapeAsBitmap(aBMP, 0);
// Size in pixel depends on dpi. Thus calculate positions relative to size.
// Front color, same as in MS Office
sal_Int32 nX = 0.93811 * aBMP.GetSizePixel().Width();
sal_Int32 nY = 0.49904 * aBMP.GetSizePixel().Height();
- ::Color aExpectedFront(88, 100, 80);
- CPPUNIT_ASSERT_MESSAGE("center color wrong",
- aExpectedFront.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
- // Left color, different from MS Office
- // The rotation brings the second light in a position, that it contributes to the left face.
- // Because the light is specular in MS Office, but current LibreOffice cannot make a second
- // light specular, the colors in MS Office and LibreOffice differ noticeably. MS Office has
- // here rgb(255, 214, 99). The expected color is the color in LibreOffice as of March 2024.
- // The test needs to be updated, when LibreOffice rendering is improved.
+ lcl_AssertColorsApproximateEqual(::Color(88, 100, 80), aBMP.GetPixelColor(nX, nY));
+ // Left color
nX = 0.078176 * aBMP.GetSizePixel().Width();
nY = 0.49904 * aBMP.GetSizePixel().Height();
- ::Color aExpectedLeft(255, 191, 75);
- CPPUNIT_ASSERT_MESSAGE("left color wrong",
- aExpectedLeft.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
- // Top color, same as in MS Office
+ lcl_AssertColorsApproximateEqual(::Color(255, 214, 99), aBMP.GetPixelColor(nX, nY));
+ // Top color
nX = 0.48860 * aBMP.GetSizePixel().Width();
nY = 0.069098 * aBMP.GetSizePixel().Height();
- ::Color aExpectedTop(106, 56, 22);
- CPPUNIT_ASSERT_MESSAGE("top color wrong",
- aExpectedTop.GetColorError(aBMP.GetPixelColor(nX, nY)) < 7);
+ lcl_AssertColorsApproximateEqual(::Color(106, 56, 22), aBMP.GetPixelColor(nX, nY));
+}
+
+CPPUNIT_TEST_FIXTURE(TestScene3d, test_material_highlight)
+{
+ // The file contains six shapes with same geometry and fill and line color. The scenes use the
+ // camera 'orthographicFront' and the lightRig 'twoPt'. The test looks at an area of highlight
+ // and at an area outside the hightlight.
+
+ loadFromFile(u"Scene3d_material_highlight.pptx");
+
+ BitmapEx aBMP;
+ getShapeAsBitmap(aBMP, 0); // material legacyPlastic
+ sal_Int32 nX = 0.75 * aBMP.GetSizePixel().Width();
+ sal_Int32 nYhigh = 0.25 * aBMP.GetSizePixel().Height();
+ sal_Int32 nYsoft = 0.75 * aBMP.GetSizePixel().Height();
+ lcl_AssertColorsApproximateEqual(::Color(255, 255, 255), aBMP.GetPixelColor(nX, nYhigh));
+ lcl_AssertColorsApproximateEqual(::Color(130, 95, 70), aBMP.GetPixelColor(nX, nYsoft));
+
+ // same geometry, thus nX, nYhigh and nYsoft unchanged
+ getShapeAsBitmap(aBMP, 1); // material warmMatte
+ lcl_AssertColorsApproximateEqual(::Color(253, 200, 164), aBMP.GetPixelColor(nX, nYhigh));
+ lcl_AssertColorsApproximateEqual(::Color(132, 96, 71), aBMP.GetPixelColor(nX, nYsoft));
+
+ getShapeAsBitmap(aBMP, 2); // material metal
+ lcl_AssertColorsApproximateEqual(::Color(255, 255, 255), aBMP.GetPixelColor(nX, nYhigh));
+ lcl_AssertColorsApproximateEqual(::Color(132, 96, 71), aBMP.GetPixelColor(nX, nYsoft));
+
+ getShapeAsBitmap(aBMP, 3); // material matte
+ lcl_AssertColorsApproximateEqual(::Color(190, 138, 102), aBMP.GetPixelColor(nX, nYhigh));
+ lcl_AssertColorsApproximateEqual(::Color(130, 95, 70), aBMP.GetPixelColor(nX, nYsoft));
+
+ getShapeAsBitmap(aBMP, 4); // material dkEdge
+ lcl_AssertColorsApproximateEqual(::Color(255, 255, 255), aBMP.GetPixelColor(nX, nYhigh));
+ lcl_AssertColorsApproximateEqual(::Color(115, 84, 62), aBMP.GetPixelColor(nX, nYsoft));
+
+ getShapeAsBitmap(aBMP, 5); // material legacyMetal
+ lcl_AssertColorsApproximateEqual(::Color(255, 255, 220), aBMP.GetPixelColor(nX, nYhigh));
+ lcl_AssertColorsApproximateEqual(::Color(86, 63, 46), aBMP.GetPixelColor(nX, nYsoft));
+}
+
+CPPUNIT_TEST_FIXTURE(TestScene3d, test_material_wireframe)
+{
+ // Given a document with a shape in 3D mode with material legacyWireframe.
+ // It uses a projection "Oblique: Top Left".
+ loadFromFile(u"Scene3d_material_wireframe.pptx");
+ uno::Reference<drawing::XShape> xShape(getShape(0, 0));
+
+ // Make sure the export to ODF has the corresponding attributes.
+ save("impress8");
+ xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
+
+ assertXPath(pXmlDoc,
+ "/office:document-content/office:body/office:presentation/draw:page/"
+ "draw:custom-shape/draw:enhanced-geometry"_ostr,
+ "extrusion-origin"_ostr, "-0.5 -0.5");
+ assertXPath(pXmlDoc,
+ "/office:document-content/office:body/office:presentation/draw:page/"
+ "draw:custom-shape/draw:enhanced-geometry"_ostr,
+ "extrusion-skew"_ostr, "30 -45");
+ assertXPath(pXmlDoc,
+ "/office:document-content/office:body/office:presentation/draw:page/"
+ "draw:custom-shape/draw:enhanced-geometry"_ostr,
+ "projection"_ostr, "parallel");
+ assertXPath(pXmlDoc,
+ "/office:document-content/office:body/office:presentation/draw:page/"
+ "draw:custom-shape/draw:enhanced-geometry"_ostr,
+ "shade-mode"_ostr, "draft");
}
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/oox/source/drawingml/scene3dhelper.cxx b/oox/source/drawingml/scene3dhelper.cxx
index d2b03ae97485..eff649a71cd7 100644
--- a/oox/source/drawingml/scene3dhelper.cxx
+++ b/oox/source/drawingml/scene3dhelper.cxx
@@ -20,12 +20,15 @@
#include <com/sun/star/drawing/Direction3D.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeParameter.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeMetalType.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
#include <com/sun/star/drawing/Position3D.hpp>
#include <com/sun/star/drawing/ProjectionMode.hpp>
#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <cmath>
+
namespace oox
{
/** This struct is used to hold values from the OOXML camera preset types.*/
@@ -941,6 +944,96 @@ void Scene3DHelper::setLightingProperties(const oox::drawingml::Shape3DPropertie
rPropertyMap.setProperty(oox::PROP_SecondLightLevel, 0.0); // prevent defaults.
}
+namespace
+/** This struct is used to hold material values for extruded custom shapes. Because we cannot yet
+ render all material propertes MS Office uses, the values are adapted to our current abilities.*/
+{
+struct MaterialValues
+{
+ std::u16string_view msMaterialPrstName; // identifies the material type
+ // Corresponds to MS Office 'Diffuse Color' and 'Ambient Color'.
+ double fDiffusion;
+ double fSpecularity; // Corresponds to MS Office 'Specular Color'.
+ // Corresponds to our 'Shininess' as 2^(Shininess/10) = nSpecularPower.
+ sal_uInt8 nSpecularPower;
+ bool bMetal; // Corresponds to MS Office 'Metal'
+ // constants com::sun::star::drawing::EnhancedCustomShapeMetalType
+ // MetalMSCompatible belongs to 'legacyMetal' material type.
+ std::optional<sal_Int16> oMetalType; // MetalODF = 0, MetalMSCompatible = 1
+ // MS Office properties 'Emissive Color', 'Diffuse Fresnel', 'Alpha Fresnel' and 'Blinn Highlight'
+ // are not contained.
+};
+} // end anonymous namespace
+
+// OOXML standard has a fixed amount of 15 material types. The type 'legacyWireframe' is special and
+// thus is handled separately. A spreadsheet with further remarks is attached to tdf#70039.
+constexpr sal_uInt16 nPrstMaterialCount(14);
+constexpr MaterialValues aPrstMaterialArray[nPrstMaterialCount]
+ = { { u"clear", 100, 60, 20, false, {} },
+ { u"dkEdge", 70, 100, 35, false, {} },
+ { u"flat", 100, 80, 50, false, {} },
+ { u"legacyMatte", 100, 0, 0, false, {} },
+ { u"legacyMetal", 66.69921875, 122.0703125, 32, true, { 1 } },
+ { u"legacyPlastic", 100, 122.0703125, 32, false, {} },
+ { u"matte", 100, 0, 0, false, {} },
+ { u"metal", 100, 100, 12, true, { 0 } },
+ { u"plastic", 100, 60, 12, true, { 0 } },
+ { u"powder", 100, 30, 10, false, {} },
+ { u"softEdge", 100, 100, 35, false, {} },
+ { u"softmetal", 100, 100, 8, true, { 0 } },
+ { u"translucentPowder", 100, 30, 10, true, { 0 } },
+ { u"warmMatte", 100, 30, 8, false, {} } };
+
+void Scene3DHelper::setMaterialProperties(const oox::drawingml::Shape3DPropertiesPtr p3DProperties,
+ oox::PropertyMap& rPropertyMap)
+{
+ if (!p3DProperties)
+ return;
+
+ // PowerPoint does not write aus prstMaterial="warmMatte", but handles it as default.
+ const sal_Int32 nMaterialID = (*p3DProperties).mnMaterial.value_or(XML_warmMatte); // token
+
+ // special handling for 'legacyWireframe'
+ if (nMaterialID == XML_legacyWireframe)
+ {
+ // This is handled via shade mode of the scene.
+ rPropertyMap.setProperty(oox::PROP_ShadeMode, css::drawing::ShadeMode_DRAFT);
+ // Notice, the color of the strokes will be different from MS Office, because LO uses the
+ // shape line color even if the line style is 'none', whereas MS Office uses contour color or
+ // Black.
+ return;
+ }
+
+ sal_Int16 nIdx(0); // Index into aPrstMaterialArray
+ while (nIdx < nPrstMaterialCount
+ && aPrstMaterialArray[nIdx].msMaterialPrstName
+ != oox::drawingml::Generic3DProperties::getPresetMaterialTypeString(nMaterialID))
+ ++nIdx;
+ if (nIdx >= nPrstMaterialCount)
+ return; // error in document
+
+ // extrusion-diffuse, extrusion-specularity-loext
+ rPropertyMap.setProperty(oox::PROP_Diffusion, aPrstMaterialArray[nIdx].fDiffusion);
+ rPropertyMap.setProperty(oox::PROP_Specularity, aPrstMaterialArray[nIdx].fSpecularity);
+
+ // extrusion-shininess
+ double fShininess = 0.0;
+ // Conversion 2^(fShininess/10) = nSpecularPower
+ if (aPrstMaterialArray[nIdx].nSpecularPower > 0)
+ fShininess = 10.0 * std::log2(aPrstMaterialArray[nIdx].nSpecularPower);
+ rPropertyMap.setProperty(oox::PROP_Shininess, fShininess);
+
+ // extrusion-metal, extrusion-metal-type
+ rPropertyMap.setProperty(oox::PROP_Metal, aPrstMaterialArray[nIdx].bMetal);
+ if (aPrstMaterialArray[nIdx].bMetal)
+ {
+ sal_Int16 eMetalType = aPrstMaterialArray[nIdx].oMetalType.value_or(0) == 1
+ ? css::drawing::EnhancedCustomShapeMetalType::MetalMSCompatible
+ : css::drawing::EnhancedCustomShapeMetalType::MetalODF;
+ rPropertyMap.setProperty(oox::PROP_MetalType, eMetalType);
+ }
+}
+
} // end namespace oox
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 195b85f893df..963391806c40 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -1002,8 +1002,12 @@ Reference< XShape > const & Shape::createAndInsert(
}
if (bHas3DEffect)
+ {
aScene3DHelper.setLightingProperties(mp3DPropertiesPtr, fShapeRotateInclCamera,
getCustomShapeProperties()->getExtrusionPropertyMap());
+ oox::Scene3DHelper::setMaterialProperties(
+ mp3DPropertiesPtr, getCustomShapeProperties()->getExtrusionPropertyMap());
+ }
if (bIsCroppedGraphic || bIs3DGraphic)
{