File bsc1174249.diff of Package libreoffice

From aa146ff3085e8149c7cf659dfb6a303dfe38bb99 Mon Sep 17 00:00:00 2001
From: Miklos Vajna <vmiklos@collabora.com>
Date: Fri, 7 Aug 2020 10:44:22 +0200
Subject: [PATCH] bsc1174249.diff

This is a combination of 2 commits.

This is the 1st commit message:

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

This is the commit message #2:

tdf#134183 PPTX: improve import of transparency in multi-step gradients

Impress core only support a single step, improve the conversion from
multi-step to single step to take transparency into account explicitly.

Once we select the widest segment, look backwards and forward if there
are other next segments which have the same RGB color, just different
transparency and include them. This helps in general, because in case a
0% or 100% transparency is mishandled, that's very visible.

(cherry picked from commit 73993fdb5d4b507694cd0edf80887d19f7e2bf9a)

Conflicts:
	oox/source/drawingml/fillproperties.cxx

Change-Id: I11d593c01a6a4b16149ce74c1408c2a39895e941
---
 oox/source/drawingml/fillproperties.cxx |  42 ++++++++--
 oox/source/export/drawingml.cxx         | 106 ++++++++++++++++--------
 2 files changed, 108 insertions(+), 40 deletions(-)

diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx
index c64b0862d225..681bf10a3e67 100644
--- a/oox/source/drawingml/fillproperties.cxx
+++ b/oox/source/drawingml/fillproperties.cxx
@@ -571,21 +571,51 @@ void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap,
                         // convert DrawingML angle (in 1/60000 degrees) to API angle (in 1/10 degrees)
                         aGradient.Angle = static_cast< sal_Int16 >( (8100 - (nDmlAngle / (PER_DEGREE / 10))) % 3600 );
                         Color aStartColor, aEndColor;
+
+                        // Try to grow the widest segment backwards: if a previous segment has the same
+                        // color, just different transparency, include it.
+                        while (aWidestSegmentStart != aGradientStops.begin())
+                        {
+                            auto it = std::prev(aWidestSegmentStart);
+                            if (it->second.getColor(rGraphicHelper, nPhClr)
+                                != aWidestSegmentStart->second.getColor(rGraphicHelper, nPhClr))
+                            {
+                                break;
+                            }
+
+                            aWidestSegmentStart = it;
+                        }
+
+                        auto aWidestSegmentEnd = std::next(aWidestSegmentStart);
+                        // Try to grow the widest segment forward: if a neext segment has the same
+                        // color, just different transparency, include it.
+                        while (aWidestSegmentEnd != std::prev(aGradientStops.end()))
+                        {
+                            auto it = std::next(aWidestSegmentEnd);
+                            if (it->second.getColor(rGraphicHelper, nPhClr)
+                                != aWidestSegmentEnd->second.getColor(rGraphicHelper, nPhClr))
+                            {
+                                break;
+                            }
+
+                            aWidestSegmentEnd = it;
+                        }
+
                         if( bSymmetric )
                         {
-                            aStartColor = std::next(aWidestSegmentStart)->second;
+                            aStartColor = aWidestSegmentEnd->second;
                             aEndColor = aWidestSegmentStart->second;
                             nBorder *= 2;
                         }
                         else if( bSwap )
                         {
-                            aStartColor = std::next(aWidestSegmentStart)->second;
+                            aStartColor = aWidestSegmentEnd->second;
                             aEndColor = aWidestSegmentStart->second;
                         }
                         else
                         {
                             aStartColor = aWidestSegmentStart->second;
-                            aEndColor = std::next(aWidestSegmentStart)->second;
+                            aEndColor = aWidestSegmentEnd->second;
                         }
 
                         SAL_INFO("oox.drawingml.gradient", "start color: " << std::hex << sal_Int32(aStartColor.getColor( rGraphicHelper, nPhClr )) << std::dec <<
@@ -596,10 +626,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 1934f118dc79..d782ad9e0a4a 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);
@@ -3458,14 +3491,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 )
     {
-- 
2.26.2

openSUSE Build Service is sponsored by