xmloff/qa/unit/data/MCGR_TransparencyBorder_restoration.pptx |binary
 xmloff/qa/unit/style.cxx                                     |   37 +++++
 xmloff/source/style/TransGradientStyle.cxx                   |   72 ++++++-----
 3 files changed, 79 insertions(+), 30 deletions(-)

New commits:
commit 8aa623714fd36cf8303ab3bdef0f26db7e69a07c
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Thu Jun 1 19:01:00 2023 +0200
Commit:     Regina Henschel <rb.hensc...@t-online.de>
CommitDate: Fri Jun 2 12:35:24 2023 +0200

    MCGR: Use tryToRecreateBorder too for transparency
    
    This is similar to 'Use tryToRecreateBorder for better BW comp with LO'
    (see commit 8259a99f41367a1d8326c9157fe1902915715879), but now for
    transparency gradients.
    
    Change-Id: I1c2e11562fa998c364896d517f4ed3bfe92f6c15
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152508
    Tested-by: Jenkins
    Reviewed-by: Regina Henschel <rb.hensc...@t-online.de>

diff --git a/xmloff/qa/unit/data/MCGR_TransparencyBorder_restoration.pptx 
b/xmloff/qa/unit/data/MCGR_TransparencyBorder_restoration.pptx
new file mode 100644
index 000000000000..f32c4d5e2b21
Binary files /dev/null and 
b/xmloff/qa/unit/data/MCGR_TransparencyBorder_restoration.pptx differ
diff --git a/xmloff/qa/unit/style.cxx b/xmloff/qa/unit/style.cxx
index f4b7f8f08012..3c5c050c0226 100644
--- a/xmloff/qa/unit/style.cxx
+++ b/xmloff/qa/unit/style.cxx
@@ -553,6 +553,43 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, 
testBorderRestoration)
     SetODFDefaultVersion(nCurrentODFVersion);
 }
 
+CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testTransparencyBorderRestoration)
+{
+    // Load document. It has a shape with transparency gradient build from 
transparency 100% at
+    // offset 0, transparency 100% at offset 0.4 and transparency 10% at 
offset 1.0. For better
+    // backward compatibility such gradient is exported with a border of 40% 
in the transparency
+    // gradient. The color itself is the same for all gradient stops.
+    // When transparency gradient-stops are integrated in ODF strict, the test 
needs to be adapted.
+    loadFromURL(u"MCGR_TransparencyBorder_restoration.pptx");
+
+    // Backup original ODF default version
+    const SvtSaveOptions::ODFDefaultVersion 
nCurrentODFVersion(GetODFDefaultVersion());
+
+    // Save to ODF_LATEST which is currently ODF 1.3 extended. Make sure 
transparency gradient-stop
+    //elements are written with offset 0 and 1, and border is written as 40%.
+    SetODFDefaultVersion(SvtSaveOptions::ODFDefaultVersion::ODFVER_LATEST);
+    save("impress8");
+    xmlDocUniquePtr pXmlDoc = parseExport("styles.xml");
+    OString sPath = "/office:document-styles/office:styles/draw:opacity[1]";
+    assertXPath(pXmlDoc, sPath + "/loext:opacity-stop[2]", "stop-opacity", 
"0.9");
+    assertXPath(pXmlDoc, sPath + "/loext:opacity-stop[2]", "offset", "1");
+    assertXPath(pXmlDoc, sPath + "/loext:opacity-stop[1]", "stop-opacity", 
"0");
+    assertXPath(pXmlDoc, sPath + "/loext:opacity-stop[1]", "offset", "0");
+    assertXPath(pXmlDoc, sPath, "border", "40%");
+
+    // Save to ODF 1.3 strict and make sure border, start and end opacity are 
suitable set.
+    SetODFDefaultVersion(SvtSaveOptions::ODFDefaultVersion::ODFVER_013);
+    save("impress8");
+    pXmlDoc = parseExport("styles.xml");
+    assertXPath(pXmlDoc, sPath + "/loext:opacity-stop", 0);
+    assertXPath(pXmlDoc, sPath, "start", "0%");
+    assertXPath(pXmlDoc, sPath, "end", "90%");
+    assertXPath(pXmlDoc, sPath, "border", "40%");
+
+    // Set back to original ODF default version.
+    SetODFDefaultVersion(nCurrentODFVersion);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/TransGradientStyle.cxx 
b/xmloff/source/style/TransGradientStyle.cxx
index d89348bbe0e8..9c268a21ff85 100644
--- a/xmloff/source/style/TransGradientStyle.cxx
+++ b/xmloff/source/style/TransGradientStyle.cxx
@@ -21,6 +21,7 @@
 
 #include <com/sun/star/awt/Gradient2.hpp>
 
+#include <basegfx/utils/bgradient.hxx>
 #include <comphelper/documentconstants.hxx>
 #include <rtl/ustrbuf.hxx>
 #include <rtl/ustring.hxx>
@@ -169,19 +170,26 @@ void XMLTransGradientStyleExport::exportXML(
     const OUString& rStrName,
     const uno::Any& rValue )
 {
-    awt::Gradient2 aGradient;
-
+    // MCGR: We try to write the gradient so, that applications without 
multi-color gradient support
+    // can render it as best as possible.
+    // This is similar to XMLGradientStyleExport::exportXML(). For details see 
there.
     if( rStrName.isEmpty() )
         return;
-
-    if( !(rValue >>= aGradient) )
+    if (!rValue.has<css::awt::Gradient2>() && 
!rValue.has<css::awt::Gradient>())
         return;
 
+    basegfx::BGradient aGradient(rValue);
+
+    // ToDo: aGradient.tryToConvertToAxial();
+
+    aGradient.tryToRecreateBorder(nullptr);
+
     OUString aStrValue;
     OUStringBuffer aOut;
 
     // Style
-    if( !SvXMLUnitConverter::convertEnum( aOut, aGradient.Style, 
pXML_GradientStyle_Enum ) )
+    if (!SvXMLUnitConverter::convertEnum(aOut, aGradient.GetGradientStyle(),
+                                         pXML_GradientStyle_Enum))
         return;
 
     // Name
@@ -197,71 +205,75 @@ void XMLTransGradientStyleExport::exportXML(
     rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE, aStrValue );
 
     // Center x/y
-    if( aGradient.Style != awt::GradientStyle_LINEAR &&
-        aGradient.Style != awt::GradientStyle_AXIAL   )
+    if (awt::GradientStyle_LINEAR != aGradient.GetGradientStyle()
+        && awt::GradientStyle_AXIAL != aGradient.GetGradientStyle())
     {
-        ::sax::Converter::convertPercent(aOut, aGradient.XOffset);
+        ::sax::Converter::convertPercent(aOut, aGradient.GetXOffset());
         aStrValue = aOut.makeStringAndClear();
         rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CX, aStrValue );
 
-        ::sax::Converter::convertPercent(aOut, aGradient.YOffset);
+        ::sax::Converter::convertPercent(aOut, aGradient.GetYOffset());
         aStrValue = aOut.makeStringAndClear();
         rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CY, aStrValue );
     }
 
-    // Transparency start
-    Color aColor(ColorTransparency, aGradient.StartColor);
-    sal_Int32 aStartValue = 100 - static_cast<sal_Int32>(((aColor.GetRed() + 
1) * 100) / 255);
-    ::sax::Converter::convertPercent( aOut, aStartValue );
+    // LO uses a gray color as transparency. ODF uses opacity in range 
[0%,100%].
+    // Default 100% opacity.
+    double fOpacityStartPerc = 100.0;
+    double fOpacityEndPerc = 100.0;
+    if (!aGradient.GetColorStops().empty())
+    {
+        fOpacityStartPerc
+            = (1.0 - 
aGradient.GetColorStops().front().getStopColor().getRed()) * 100.0;
+        fOpacityEndPerc = (1.0 - 
aGradient.GetColorStops().back().getStopColor().getRed()) * 100.0;
+    }
+
+    // Opacity start
+    ::sax::Converter::convertPercent(aOut, 
static_cast<sal_Int32>(std::lround(fOpacityStartPerc)));
     aStrValue = aOut.makeStringAndClear();
     rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_START, aStrValue );
 
-    // Transparency end
-    aColor = Color(ColorTransparency, aGradient.EndColor);
-    sal_Int32 aEndValue = 100 - static_cast<sal_Int32>(((aColor.GetRed() + 1) 
* 100) / 255);
-    ::sax::Converter::convertPercent( aOut, aEndValue );
+    // Opacity end
+    ::sax::Converter::convertPercent( aOut, 
static_cast<sal_Int32>(std::lround(fOpacityEndPerc)));
     aStrValue = aOut.makeStringAndClear();
     rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_END, aStrValue );
 
     // Angle
-    if( aGradient.Style != awt::GradientStyle_RADIAL )
+    if (awt::GradientStyle_RADIAL != aGradient.GetGradientStyle())
     {
-        ::sax::Converter::convertAngle(aOut, aGradient.Angle, 
rExport.getSaneDefaultVersion());
+        ::sax::Converter::convertAngle(aOut, aGradient.GetAngle().get(),
+                                       rExport.getSaneDefaultVersion());
         aStrValue = aOut.makeStringAndClear();
         rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_GRADIENT_ANGLE, 
aStrValue );
     }
 
     // Border
-    ::sax::Converter::convertPercent( aOut, aGradient.Border );
+    ::sax::Converter::convertPercent(aOut, aGradient.GetBorder());
     aStrValue = aOut.makeStringAndClear();
     rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_BORDER, aStrValue );
 
     // ctor writes start tag. End-tag is written by destructor at block end.
-    SvXMLElementExport rElem( rExport,
-                              XML_NAMESPACE_DRAW, XML_OPACITY,
-                              true, false );
+    SvXMLElementExport rElem(rExport, XML_NAMESPACE_DRAW, XML_OPACITY, true, 
false);
 
     // Write child elements <loext:opacity-stop>
     // Do not export in standard ODF 1.3 or older.
     if ((rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) 
== 0)
         return;
-    sal_Int32 nCount = aGradient.ColorStops.getLength();
-    if (nCount == 0)
+    if (aGradient.GetColorStops().empty())
         return;
+
     double fPreviousOffset = 0.0;
-    for (auto& aCandidate : aGradient.ColorStops)
+    for (auto& aCandidate : aGradient.GetColorStops())
     {
         // Attribute svg:offset. Make sure offsets are increasing.
-        double fOffset = std::clamp<double>(aCandidate.StopOffset, 0.0, 1.0);
+        double fOffset = std::clamp<double>(aCandidate.getStopOffset(), 0.0, 
1.0);
         if (fOffset < fPreviousOffset)
             fOffset = fPreviousOffset;
         rExport.AddAttribute(XML_NAMESPACE_SVG, XML_OFFSET, 
OUString::number(fOffset));
         fPreviousOffset = fOffset;
 
         // Attribute svg:stop-opacity, data type zeroToOneDecimal
-        rendering::RGBColor aDecimalColor = aCandidate.StopColor;
-        // transparency is encoded as gray, 1.0 corresponds to full transparent
-        double fOpacity = std::clamp<double>(1.0 - aDecimalColor.Red, 0.0, 
1.0);
+        double fOpacity = std::clamp<double>(1.0 - 
aCandidate.getStopColor().getRed(), 0.0, 1.0);
         rExport.AddAttribute(XML_NAMESPACE_SVG, XML_STOP_OPACITY, 
OUString::number(fOpacity));
 
         // write opacity stop element

Reply via email to