svx/qa/unit/customshapes.cxx                      |   42 ++++++++++++++++++++++
 svx/qa/unit/data/tdf160421_3D_FlipLight.odp       |binary
 svx/source/customshapes/EnhancedCustomShape3d.cxx |    8 ++++
 3 files changed, 50 insertions(+)

New commits:
commit 9761d4239de6398d4f6ecf08356f2ce18e502a04
Author:     Regina Henschel <[email protected]>
AuthorDate: Fri Mar 29 22:44:45 2024 +0100
Commit:     Regina Henschel <[email protected]>
CommitDate: Sat Mar 30 21:19:25 2024 +0100

    tdf#160421 flip lights too for flipped extruded shapes
    
    If an extruded custom shape is mirrored, the lights in the scene are
    also mirrored. This should not happen. MS Office keeps the light
    direction in relation to the camera direction for binary files and pptx
    files with legacy camera. We should do the same, especially since the UI
    does not allow the user to set the light directions at arbitrary angles.
    Otherwise the shape receives only ambient light.
    
    Change-Id: I091d78c581b3d247f8b0680cd57654e3df330cdd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165562
    Tested-by: Jenkins
    Reviewed-by: Regina Henschel <[email protected]>

diff --git a/svx/qa/unit/customshapes.cxx b/svx/qa/unit/customshapes.cxx
index 617c97300c43..92770e9f2320 100644
--- a/svx/qa/unit/customshapes.cxx
+++ b/svx/qa/unit/customshapes.cxx
@@ -58,6 +58,9 @@ protected:
     // get shape nShapeIndex from page 0
     uno::Reference<drawing::XShape> getShape(sal_uInt8 nShapeIndex);
     sal_uInt8 countShapes();
+    // fX and fY are positions relative to the size of the bitmap of the shape
+    // Thus the position is indepedent from DPI
+    Color getColor(uno::Reference<drawing::XShape> xShape, const double& fX, 
const double& fY);
 };
 
 uno::Reference<drawing::XShape> CustomshapesTest::getShape(sal_uInt8 
nShapeIndex)
@@ -84,6 +87,18 @@ sal_uInt8 CustomshapesTest::countShapes()
     return xDrawPage->getCount();
 }
 
+Color CustomshapesTest::getColor(uno::Reference<drawing::XShape> xShape, const 
double& fX,
+                                 const double& fY)
+{
+    GraphicHelper::SaveShapeAsGraphicToPath(mxComponent, xShape, "image/png", 
maTempFile.GetURL());
+    SvFileStream aFileStream(maTempFile.GetURL(), StreamMode::READ);
+    vcl::PngImageReader aPNGReader(aFileStream);
+    Bitmap aBMP = aPNGReader.read().GetBitmap();
+    Size aSize = aBMP.GetSizePixel();
+    BitmapScopedReadAccess pRead(aBMP);
+    return pRead->GetColor(aSize.Height() * fY, aSize.Width() * fX);
+}
+
 CPPUNIT_TEST_FIXTURE(CustomshapesTest, testTdf150302)
 {
     loadFromFile(u"FontworkSameLetterHeights.fodg");
@@ -1376,6 +1391,33 @@ CPPUNIT_TEST_FIXTURE(CustomshapesTest, 
testTdf153000_MS0_SPT_25_31)
         CPPUNIT_ASSERT_EQUAL(aExpected[i], aCoordinates.getLength());
     }
 }
+
+CPPUNIT_TEST_FIXTURE(CustomshapesTest, testTdf160421_3D_FlipLight)
+{
+    // The document contains (0)an extruded 'rectangle' custom shape which is 
illuminated with front
+    // light, (1) this shape vertically flipped and (2) this shape 
horizontally flipped.
+    // When the shape is flipped vertically or horizontally, the light 
direction should not
+    // change. MS Office behaves in this way for ppt and pptx and it is 
meaningful as flipping is
+    // applied to the shape, not to the scene.
+
+    // Load document.
+    loadFromFile(u"tdf160421_3D_FlipLight.odp");
+
+    // Get color from untransformed shape (0).
+    uno::Reference<drawing::XShape> xShape = getShape(0);
+    Color aNormalColor = getColor(xShape, 0.6, 0.6);
+
+    // Test that color from vertically flipped shape (1) is same as normal 
color. Without the fix
+    // it was only build from ambient light and thus much darker.
+    xShape = getShape(1);
+    sal_uInt16 nColorDistance = aNormalColor.GetColorError(getColor(xShape, 
0.6, 0.6));
+    CPPUNIT_ASSERT_LESS(sal_uInt16(6), nColorDistance);
+
+    // Same for horizontally flipped shape (2)
+    xShape = getShape(2);
+    nColorDistance = aNormalColor.GetColorError(getColor(xShape, 0.6, 0.6));
+    CPPUNIT_ASSERT_LESS(sal_uInt16(6), nColorDistance);
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/qa/unit/data/tdf160421_3D_FlipLight.odp 
b/svx/qa/unit/data/tdf160421_3D_FlipLight.odp
new file mode 100644
index 000000000000..2decc51e3e6d
Binary files /dev/null and b/svx/qa/unit/data/tdf160421_3D_FlipLight.odp differ
diff --git a/svx/source/customshapes/EnhancedCustomShape3d.cxx 
b/svx/source/customshapes/EnhancedCustomShape3d.cxx
index 2763c9e47e00..d2f9de215f65 100644
--- a/svx/source/customshapes/EnhancedCustomShape3d.cxx
+++ b/svx/source/customshapes/EnhancedCustomShape3d.cxx
@@ -838,6 +838,14 @@ rtl::Reference<SdrObject> 
EnhancedCustomShape3d::Create3DObject(
             basegfx::B3DVector aLight2Vector(aSecondLightDirection.DirectionX, 
-aSecondLightDirection.DirectionY, aSecondLightDirection.DirectionZ);
             aLight2Vector.normalize();
 
+            // tdf#160421 a single flip inverts the light directions currently 
(March 2024). So invert
+            // their directions here for rendering.
+            if (bIsMirroredX != bIsMirroredY)
+            {
+                aLight1Vector *= -1.0;
+                aLight2Vector *= -1.0;
+            }
+
             // Light Intensity
 
             // For "FirstLight" the 3D-Scene light "1" is regularly used. In 
case of surface "Matte"

Reply via email to