summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--filter/qa/unit/data/semi-transparent-line.odgbin0 -> 8874 bytes
-rw-r--r--filter/qa/unit/svg.cxx34
-rw-r--r--filter/source/svg/svgwriter.cxx47
-rw-r--r--test/source/xmltesttools.cxx5
4 files changed, 61 insertions, 25 deletions
diff --git a/filter/qa/unit/data/semi-transparent-line.odg b/filter/qa/unit/data/semi-transparent-line.odg
new file mode 100644
index 000000000000..2d28a694cea5
--- /dev/null
+++ b/filter/qa/unit/data/semi-transparent-line.odg
Binary files differ
diff --git a/filter/qa/unit/svg.cxx b/filter/qa/unit/svg.cxx
index d6bb68283b74..8e6524c688ba 100644
--- a/filter/qa/unit/svg.cxx
+++ b/filter/qa/unit/svg.cxx
@@ -20,9 +20,7 @@
using namespace ::com::sun::star;
-#if !defined MACOSX
char const DATA_DIRECTORY[] = "/filter/qa/unit/data/";
-#endif
/// SVG filter tests.
class SvgFilterTest : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools
@@ -34,10 +32,8 @@ public:
void setUp() override;
void tearDown() override;
void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override;
-#if !defined MACOSX
uno::Reference<lang::XComponent>& getComponent() { return mxComponent; }
void load(const OUString& rURL);
-#endif
};
void SvgFilterTest::setUp()
@@ -55,13 +51,11 @@ void SvgFilterTest::tearDown()
test::BootstrapFixture::tearDown();
}
-#if !defined MACOSX
void SvgFilterTest::load(const OUString& rFileName)
{
OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + rFileName;
mxComponent = loadFromDesktop(aURL);
}
-#endif
void SvgFilterTest::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx)
{
@@ -100,6 +94,34 @@ CPPUNIT_TEST_FIXTURE(SvgFilterTest, testPreserveJpg)
#endif
}
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testSemiTransparentLine)
+{
+ // Load a document with a semi-transparent line shape.
+ load("semi-transparent-line.odg");
+
+ // Export it to SVG.
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("draw_svg_Export");
+ aMediaDescriptor["OutputStream"] <<= xOut;
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Get the style of the group around the actual <path> element.
+ xmlDocPtr pXmlDoc = parseXmlStream(&aStream);
+ OUString aStyle = getXPath(
+ pXmlDoc, "//svg:g[@class='com.sun.star.drawing.LineShape']/svg:g/svg:g", "style");
+ OUString aPrefix("opacity: ");
+ // Without the accompanying fix in place, this test would have failed, as the style was
+ // "mask:url(#mask1)", not "opacity: <value>".
+ CPPUNIT_ASSERT(aStyle.startsWith(aPrefix));
+ int nPercent = std::round(aStyle.copy(aPrefix.getLength()).toDouble() * 100);
+ // Make sure that the line is still 30% opaque, rather than completely invisible.
+ CPPUNIT_ASSERT_EQUAL(30, nPercent);
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index 8d491d122d0b..c276fd903048 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -2382,32 +2382,43 @@ void SVGActionWriter::ImplWriteMask( GDIMetaFile& rMtf,
if( nMoveX || nMoveY )
rMtf.Move( nMoveX, nMoveY );
- OUString aMaskId = "mask" + OUString::number( mnCurMaskId++ );
-
+ OUString aStyle;
+ if (rGradient.GetStartColor() == rGradient.GetEndColor())
{
- SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true );
+ // Special case: constant alpha value.
+ const Color& rColor = rGradient.GetStartColor();
+ const double fOpacity = 1.0 - static_cast<double>(rColor.GetLuminance()) / 255;
+ aStyle = "opacity: " + OUString::number(fOpacity);
+ }
+ else
+ {
+ OUString aMaskId = "mask" + OUString::number(mnCurMaskId++);
- mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aMaskId );
{
- SvXMLElementExport aElemMask( mrExport, XML_NAMESPACE_NONE, "mask", true, true );
+ SvXMLElementExport aElemDefs(mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true);
- const tools::PolyPolygon aPolyPolygon( tools::PolyPolygon( tools::Rectangle( rDestPt, rDestSize ) ) );
- Gradient aGradient( rGradient );
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrId, aMaskId);
+ {
+ SvXMLElementExport aElemMask(mrExport, XML_NAMESPACE_NONE, "mask", true, true);
- // swap gradient stops to adopt SVG mask
- Color aTmpColor( aGradient.GetStartColor() );
- sal_uInt16 nTmpIntensity( aGradient.GetStartIntensity() );
- aGradient.SetStartColor( aGradient.GetEndColor() );
- aGradient.SetStartIntensity( aGradient.GetEndIntensity() ) ;
- aGradient.SetEndColor( aTmpColor );
- aGradient.SetEndIntensity( nTmpIntensity );
+ const tools::PolyPolygon aPolyPolygon(tools::PolyPolygon(tools::Rectangle(rDestPt, rDestSize)));
+ Gradient aGradient(rGradient);
- ImplWriteGradientEx( aPolyPolygon, aGradient, nWriteFlags );
+ // swap gradient stops to adopt SVG mask
+ Color aTmpColor(aGradient.GetStartColor());
+ sal_uInt16 nTmpIntensity(aGradient.GetStartIntensity());
+ aGradient.SetStartColor(aGradient.GetEndColor());
+ aGradient.SetStartIntensity(aGradient.GetEndIntensity());
+ aGradient.SetEndColor(aTmpColor);
+ aGradient.SetEndIntensity(nTmpIntensity);
+
+ ImplWriteGradientEx(aPolyPolygon, aGradient, nWriteFlags);
+ }
}
- }
- OUString aMaskStyle = "mask:url(#" + aMaskId + ")";
- mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aMaskStyle );
+ aStyle = "mask:url(#" + aMaskId + ")";
+ }
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStyle, aStyle);
{
SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
diff --git a/test/source/xmltesttools.cxx b/test/source/xmltesttools.cxx
index b4a74aa4a8b4..f89c127171bd 100644
--- a/test/source/xmltesttools.cxx
+++ b/test/source/xmltesttools.cxx
@@ -12,6 +12,7 @@
#include <memory>
#include <vcl/mtfxmldump.hxx>
+#include <sal/log.hxx>
namespace {
@@ -53,7 +54,9 @@ xmlDocPtr XmlTestTools::parseXmlStream(SvStream* pStream)
std::unique_ptr<sal_uInt8[]> pBuffer(new sal_uInt8[nSize + 1]);
pStream->ReadBytes(pBuffer.get(), nSize);
pBuffer[nSize] = 0;
- return xmlParseDoc(reinterpret_cast<xmlChar*>(pBuffer.get()));
+ auto pCharBuffer = reinterpret_cast<xmlChar*>(pBuffer.get());
+ SAL_INFO("test", "XmlTestTools::parseXmlStream: pBuffer is '" << pCharBuffer << "'");
+ return xmlParseDoc(pCharBuffer);
}
xmlDocPtr XmlTestTools::dumpAndParse(MetafileXmlDump& rDumper, const GDIMetaFile& rGDIMetaFile)