summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRegina Henschel <rb.henschel@t-online.de>2023-06-01 19:01:00 +0200
committerRegina Henschel <rb.henschel@t-online.de>2023-06-02 12:35:24 +0200
commit8aa623714fd36cf8303ab3bdef0f26db7e69a07c (patch)
tree313c72191d84e8ed0e97ba065f1381dcd72babd5
parent920e76f15b78398de62002e30002f4f8e0fee7c1 (diff)
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.henschel@t-online.de>
-rw-r--r--xmloff/qa/unit/data/MCGR_TransparencyBorder_restoration.pptxbin0 -> 15436 bytes
-rw-r--r--xmloff/qa/unit/style.cxx37
-rw-r--r--xmloff/source/style/TransGradientStyle.cxx72
3 files changed, 79 insertions, 30 deletions
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
--- /dev/null
+++ b/xmloff/qa/unit/data/MCGR_TransparencyBorder_restoration.pptx
Binary files 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