oox/source/drawingml/fillproperties.cxx                   |    6 
 oox/source/export/drawingml.cxx                           |  106 +++++++++-----
 sd/qa/unit/data/odp/tdf128345_FullTransparentGradient.odp |binary
 sd/qa/unit/data/odp/tdf128345_GradientAxial.odp           |binary
 sd/qa/unit/data/odp/tdf128345_GradientLinear.odp          |binary
 sd/qa/unit/data/odp/tdf128345_GradientRadial.odp          |binary
 sd/qa/unit/export-tests-ooxml1.cxx                        |   80 ++++++++++
 7 files changed, 155 insertions(+), 37 deletions(-)

New commits:
commit 0ff6f5ad44a5fb9903c9a905d2ec55248ee75315
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Tue Jul 14 22:52:56 2020 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Aug 7 10:29:11 2020 +0200

    tdf#128345 pptx export: add transparence gradient in solid fill
    
    In case of solid color fill a transparence gradient was not saved.
    OOXML has no separate element for gradient transparency but has
    transparency in color gradient stop elements. The patch detects
    a transparence gradient, combines it with the fill color and exports
    it as gradFill element.
    The import was already correct, besides a wrong start or end value
    in case of a symmetric gradient, which becomes AXIAL in LibreOffice.
    
    (cherry picked from commit d187f22b7ff73954e1da39fb954c64bc315298cb)
    
    Conflicts:
            oox/source/drawingml/fillproperties.cxx
            sd/qa/unit/export-tests-ooxml1.cxx
    
    Change-Id: I4243656821629f90125d0408a38165a8a29e6e24
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100286
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/oox/source/drawingml/fillproperties.cxx 
b/oox/source/drawingml/fillproperties.cxx
index caa54b82ca34..f963f103d2c8 100644
--- a/oox/source/drawingml/fillproperties.cxx
+++ b/oox/source/drawingml/fillproperties.cxx
@@ -529,10 +529,8 @@ void FillProperties::pushToPropMap( ShapePropertyMap& 
rPropMap,
                         aGradient.StartColor = sal_Int32(aStartColor.getColor( 
rGraphicHelper, nPhClr ));
                         aGradient.EndColor = sal_Int32(aEndColor.getColor( 
rGraphicHelper, nPhClr ));
 
-                        if( aStartColor.hasTransparency() )
-                            nStartTrans = 
aStartColor.getTransparency()*255/100;
-                        if( aEndColor.hasTransparency() )
-                            nEndTrans = aEndColor.getTransparency()*255/100;
+                        nStartTrans = aStartColor.hasTransparency() ? 
aStartColor.getTransparency()*255/100 : 0;
+                        nEndTrans = aEndColor.hasTransparency() ? 
aEndColor.getTransparency()*255/100 : 0;
 
                         aGradient.Border = rtl::math::round(100*nBorder);
                     }
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 327d5a27931a..b9c6403caff2 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -405,8 +405,38 @@ void DrawingML::WriteSolidFill( const Reference< 
XPropertySet >& rXPropSet )
         nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
     }
 
+    // OOXML has no separate transparence gradient but uses transparency in 
the gradient stops.
+    // So we merge transparency and color and use gradient fill in such case.
+    awt::Gradient aTransparenceGradient;
+    bool bNeedGradientFill(false);
+    if (GetProperty(rXPropSet, "FillTransparenceGradient"))
+    {
+        mAny >>= aTransparenceGradient;
+        if (aTransparenceGradient.StartColor != aTransparenceGradient.EndColor)
+            bNeedGradientFill = true;
+        else if (aTransparenceGradient.StartColor != 0)
+            nAlpha = GetAlphaFromTransparenceGradient(aTransparenceGradient, 
true);
+    }
+
     // write XML
-    if ( nFillColor != nOriginalColor )
+    if (bNeedGradientFill)
+    {
+        awt::Gradient aPseudoColorGradient;
+        aPseudoColorGradient.XOffset = aTransparenceGradient.XOffset;
+        aPseudoColorGradient.YOffset = aTransparenceGradient.YOffset;
+        aPseudoColorGradient.StartIntensity = 100;
+        aPseudoColorGradient.EndIntensity = 100;
+        aPseudoColorGradient.Angle = aTransparenceGradient.Angle;
+        aPseudoColorGradient.Border = aTransparenceGradient.Border;
+        aPseudoColorGradient.Style = aTransparenceGradient.Style;
+        aPseudoColorGradient.StartColor = nFillColor;
+        aPseudoColorGradient.EndColor = nFillColor;
+        aPseudoColorGradient.StepCount = aTransparenceGradient.StepCount;
+        mpFS->startElementNS(XML_a, XML_gradFill, XML_rotWithShape, "0");
+        WriteGradientFill(aPseudoColorGradient, aTransparenceGradient);
+        mpFS->endElementNS( XML_a, XML_gradFill );
+    }
+    else if ( nFillColor != nOriginalColor )
     {
         // the user has set a different color for the shape
         WriteSolidFill( ::Color(nFillColor & 0xffffff), nAlpha );
@@ -586,25 +616,25 @@ void DrawingML::WriteGrabBagGradientFill( const Sequence< 
PropertyValue >& aGrad
 void DrawingML::WriteGradientFill(awt::Gradient rGradient, awt::Gradient 
rTransparenceGradient,
                                   const uno::Reference<beans::XPropertySet>& 
rXPropSet)
 {
+    sal_Int32 nStartAlpha;
+    sal_Int32 nEndAlpha;
+    if( rXPropSet.is() && GetProperty(rXPropSet, "FillTransparence") )
+    {
+        sal_Int32 nTransparency = 0;
+        mAny >>= nTransparency;
+        nStartAlpha = nEndAlpha = (MAX_PERCENT - (PER_PERCENT * 
nTransparency));
+    }
+    else
+    {
+        nStartAlpha = GetAlphaFromTransparenceGradient(rTransparenceGradient, 
true);
+        nEndAlpha = GetAlphaFromTransparenceGradient(rTransparenceGradient, 
false);
+    }
     switch( rGradient.Style )
     {
         default:
         case awt::GradientStyle_LINEAR:
         {
             mpFS->startElementNS(XML_a, XML_gsLst);
-            sal_Int32 nStartAlpha;
-            sal_Int32 nEndAlpha;
-            if( rXPropSet.is() && GetProperty(rXPropSet, "FillTransparence") )
-            {
-                sal_Int32 nTransparency = 0;
-                mAny >>= nTransparency;
-                nStartAlpha = nEndAlpha = (MAX_PERCENT - (PER_PERCENT * 
nTransparency));
-            }
-            else
-            {
-                nStartAlpha = 
GetAlphaFromTransparenceGradient(rTransparenceGradient, true);
-                nEndAlpha = 
GetAlphaFromTransparenceGradient(rTransparenceGradient, false);
-            }
             WriteGradientStop(rGradient.Border, 
ColorWithIntensity(rGradient.StartColor, rGradient.StartIntensity),
                               nStartAlpha);
             WriteGradientStop(100, ColorWithIntensity(rGradient.EndColor, 
rGradient.EndIntensity),
@@ -619,23 +649,22 @@ void DrawingML::WriteGradientFill(awt::Gradient 
rGradient, awt::Gradient rTransp
         case awt::GradientStyle_AXIAL:
         {
             mpFS->startElementNS(XML_a, XML_gsLst);
-            sal_Int32 nStartAlpha;
-            sal_Int32 nEndAlpha;
-            if (rXPropSet.is() && GetProperty(rXPropSet, "FillTransparence"))
-            {
-                sal_Int32 nTransparency = 0;
-                mAny >>= nTransparency;
-                nStartAlpha = nEndAlpha = (MAX_PERCENT - (PER_PERCENT * 
nTransparency));
-            }
-            else
-            {
-                nStartAlpha = 
GetAlphaFromTransparenceGradient(rTransparenceGradient, true);
-                nEndAlpha = 
GetAlphaFromTransparenceGradient(rTransparenceGradient, false);
-            }
             WriteGradientStop(0, ColorWithIntensity(rGradient.EndColor, 
rGradient.EndIntensity),
                               nEndAlpha);
+            if (rGradient.Border > 0 && rGradient.Border < 100)
+            {
+                WriteGradientStop(rGradient.Border/2,
+                                  ColorWithIntensity(rGradient.EndColor, 
rGradient.EndIntensity),
+                                  nEndAlpha);
+            }
             WriteGradientStop(50, ColorWithIntensity(rGradient.StartColor, 
rGradient.StartIntensity),
                               nStartAlpha);
+            if (rGradient.Border > 0 && rGradient.Border < 100)
+            {
+                WriteGradientStop(100 - rGradient.Border/2,
+                                  ColorWithIntensity(rGradient.EndColor, 
rGradient.EndIntensity),
+                                  nEndAlpha);
+            }
             WriteGradientStop(100, ColorWithIntensity(rGradient.EndColor, 
rGradient.EndIntensity),
                               nEndAlpha);
             mpFS->endElementNS(XML_a, XML_gsLst);
@@ -648,15 +677,19 @@ void DrawingML::WriteGradientFill(awt::Gradient 
rGradient, awt::Gradient rTransp
         case awt::GradientStyle_RADIAL:
         {
             mpFS->startElementNS(XML_a, XML_gsLst);
-            WriteGradientStop(0, ColorWithIntensity(rGradient.EndColor, 
rGradient.EndIntensity));
+            WriteGradientStop(0, ColorWithIntensity(rGradient.EndColor, 
rGradient.EndIntensity),
+                              nEndAlpha);
             if (rGradient.Border > 0 && rGradient.Border < 100)
+            {
                 // Map border to an additional gradient stop, which has the
                 // same color as the final stop.
-                WriteGradientStop(
-                    100 - rGradient.Border,
-                    ColorWithIntensity(rGradient.StartColor, 
rGradient.StartIntensity));
+                WriteGradientStop(100 - rGradient.Border,
+                                  ColorWithIntensity(rGradient.StartColor, 
rGradient.StartIntensity),
+                                  nStartAlpha);
+            }
             WriteGradientStop(100,
-                              ColorWithIntensity(rGradient.StartColor, 
rGradient.StartIntensity));
+                              ColorWithIntensity(rGradient.StartColor, 
rGradient.StartIntensity),
+                              nStartAlpha);
             mpFS->endElementNS(XML_a, XML_gsLst);
 
             WriteRadialGradientPath(rGradient, mpFS);
@@ -3468,14 +3501,21 @@ void DrawingML::WriteFill( const Reference< 
XPropertySet >& xPropSet )
     FillStyle aFillStyle( FillStyle_NONE );
     xPropSet->getPropertyValue( "FillStyle" ) >>= aFillStyle;
 
+    // map full transparent background to no fill
     if ( aFillStyle == FillStyle_SOLID && GetProperty( xPropSet, 
"FillTransparence" ) )
     {
-        // map full transparent background to no fill
         sal_Int16 nVal = 0;
         xPropSet->getPropertyValue( "FillTransparence" ) >>= nVal;
         if ( nVal == 100 )
             aFillStyle = FillStyle_NONE;
     }
+    if (aFillStyle == FillStyle_SOLID && GetProperty( xPropSet, 
"FillTransparenceGradient"))
+    {
+        awt::Gradient aTransparenceGradient;
+        mAny >>= aTransparenceGradient;
+        if (aTransparenceGradient.StartColor == 0xffffff && 
aTransparenceGradient.EndColor == 0xffffff)
+            aFillStyle = FillStyle_NONE;
+    }
 
     switch( aFillStyle )
     {
diff --git a/sd/qa/unit/data/odp/tdf128345_FullTransparentGradient.odp 
b/sd/qa/unit/data/odp/tdf128345_FullTransparentGradient.odp
new file mode 100644
index 000000000000..904490d4313f
Binary files /dev/null and 
b/sd/qa/unit/data/odp/tdf128345_FullTransparentGradient.odp differ
diff --git a/sd/qa/unit/data/odp/tdf128345_GradientAxial.odp 
b/sd/qa/unit/data/odp/tdf128345_GradientAxial.odp
new file mode 100644
index 000000000000..55b8ec1aac60
Binary files /dev/null and b/sd/qa/unit/data/odp/tdf128345_GradientAxial.odp 
differ
diff --git a/sd/qa/unit/data/odp/tdf128345_GradientLinear.odp 
b/sd/qa/unit/data/odp/tdf128345_GradientLinear.odp
new file mode 100644
index 000000000000..1eadfa11f08b
Binary files /dev/null and b/sd/qa/unit/data/odp/tdf128345_GradientLinear.odp 
differ
diff --git a/sd/qa/unit/data/odp/tdf128345_GradientRadial.odp 
b/sd/qa/unit/data/odp/tdf128345_GradientRadial.odp
new file mode 100644
index 000000000000..634d1dc1bd5f
Binary files /dev/null and b/sd/qa/unit/data/odp/tdf128345_GradientRadial.odp 
differ
diff --git a/sd/qa/unit/export-tests-ooxml1.cxx 
b/sd/qa/unit/export-tests-ooxml1.cxx
index 0da3de5332b6..a71952ffd413 100644
--- a/sd/qa/unit/export-tests-ooxml1.cxx
+++ b/sd/qa/unit/export-tests-ooxml1.cxx
@@ -91,6 +91,10 @@ public:
     void testRoundtripPrstDash();
     void testDashOnHairline();
     void testCustomshapeBitmapfillSrcrect();
+    void testTdf128345FullTransparentGradient();
+    void testTdf128345GradientLinear();
+    void testTdf128345GradientRadial();
+    void testTdf128345GradientAxial();
 
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest1);
 
@@ -131,6 +135,10 @@ public:
     CPPUNIT_TEST(testRoundtripPrstDash);
     CPPUNIT_TEST(testDashOnHairline);
     CPPUNIT_TEST(testCustomshapeBitmapfillSrcrect);
+    CPPUNIT_TEST(testTdf128345FullTransparentGradient);
+    CPPUNIT_TEST(testTdf128345GradientLinear);
+    CPPUNIT_TEST(testTdf128345GradientRadial);
+    CPPUNIT_TEST(testTdf128345GradientAxial);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -1096,6 +1104,78 @@ void 
SdOOXMLExportTest1::testCustomshapeBitmapfillSrcrect()
     CPPUNIT_ASSERT_EQUAL(4.0, fRightPercent);
 }
 
+void SdOOXMLExportTest1::testTdf128345FullTransparentGradient()
+{
+    ::sd::DrawDocShellRef xDocShRef
+        = 
loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/odp/tdf128345_FullTransparentGradient.odp"),
 ODP);
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+    xDocShRef->DoClose();
+
+    // Make sure the shape has no fill. Without the patch, fill was solid red.
+    xmlDocPtr pXmlDoc = parseExport(tempFile, "ppt/slides/slide1.xml");
+    const OString sPathStart("//p:sld/p:cSld/p:spTree/p:sp/p:spPr");
+    assertXPath(pXmlDoc, sPathStart + "/a:noFill");
+}
+
+void SdOOXMLExportTest1::testTdf128345GradientLinear()
+{
+    ::sd::DrawDocShellRef xDocShRef
+        = 
loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/odp/tdf128345_GradientLinear.odp"),
 ODP);
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+    xDocShRef->DoClose();
+
+    // Make sure the shape has a lin fill. Without the patch, fill was solid 
red.
+    xmlDocPtr pXmlDoc = parseExport(tempFile, "ppt/slides/slide1.xml");
+    const OString sPathStart("//p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:gradFill");
+    assertXPath(pXmlDoc, sPathStart + "/a:lin", "ang", "3600000");
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs",2);
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]", "pos", "25000");
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]/a:srgbClr", "val", 
"ff0000");
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]/a:srgbClr/a:alpha", 
"val", "20000");
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]", "pos", "100000");
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]/a:srgbClr", "val", 
"ff0000");
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]/a:srgbClr/a:alpha", 
"val", "80000");
+}
+
+void SdOOXMLExportTest1::testTdf128345GradientRadial()
+{
+    ::sd::DrawDocShellRef xDocShRef
+        = 
loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/odp/tdf128345_GradientRadial.odp"),
 ODP);
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+    xDocShRef->DoClose();
+
+    // Make sure the shape has transparency. In OOXML alpha means 'opacity' 
with default
+    // 100000 for full opak, so only the full transparency with val 0 should 
be written.
+    xmlDocPtr pXmlDoc = parseExport(tempFile, "ppt/slides/slide1.xml");
+    const OString sPathStart("//p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:gradFill");
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs",2);
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]/a:srgbClr", "val", 
"ff0000");
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]/a:srgbClr/a:alpha", 0);
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]/a:srgbClr", "val", 
"ffffff");
+    assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]/a:srgbClr/a:alpha", 
"val", "0");
+}
+
+void SdOOXMLExportTest1::testTdf128345GradientAxial()
+{
+    // Without the patch, symmtetric linear gradient with full transparence 
outside and
+    // full opak in the middle were imported as full transparent.
+    ::sd::DrawDocShellRef xDocShRef
+        = 
loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/odp/tdf128345_GradientAxial.odp"),
 ODP);
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX);
+    uno::Reference<beans::XPropertySet> xShapePropSet(getShapeFromPage(0, 0, 
xDocShRef));
+
+    awt::Gradient aTransparenceGradient;
+    xShapePropSet->getPropertyValue("FillTransparenceGradient") >>= 
aTransparenceGradient;
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0x000000), 
aTransparenceGradient.StartColor);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0xffffff), aTransparenceGradient.EndColor);
+    CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_AXIAL, 
aTransparenceGradient.Style);
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest1);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to