diff options
-rw-r--r-- | oox/inc/drawingml/scene3dhelper.hxx | 13 | ||||
-rw-r--r-- | oox/qa/unit/data/Scene3d_material_highlight.pptx | bin | 0 -> 19845 bytes | |||
-rw-r--r-- | oox/qa/unit/data/Scene3d_material_wireframe.pptx | bin | 0 -> 15288 bytes | |||
-rw-r--r-- | oox/qa/unit/testscene3d.cxx | 168 | ||||
-rw-r--r-- | oox/source/drawingml/scene3dhelper.cxx | 93 | ||||
-rw-r--r-- | oox/source/drawingml/shape.cxx | 4 |
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 Binary files differnew file mode 100644 index 000000000000..c299c21bc68c --- /dev/null +++ b/oox/qa/unit/data/Scene3d_material_highlight.pptx diff --git a/oox/qa/unit/data/Scene3d_material_wireframe.pptx b/oox/qa/unit/data/Scene3d_material_wireframe.pptx Binary files differnew file mode 100644 index 000000000000..f72baeb25178 --- /dev/null +++ b/oox/qa/unit/data/Scene3d_material_wireframe.pptx 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) { |