diff options
-rw-r--r-- | filter/qa/unit/data/semi-transparent-line.odg | bin | 0 -> 8874 bytes | |||
-rw-r--r-- | filter/qa/unit/svg.cxx | 34 | ||||
-rw-r--r-- | filter/source/svg/svgwriter.cxx | 47 | ||||
-rw-r--r-- | test/source/xmltesttools.cxx | 5 |
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 Binary files differnew file mode 100644 index 000000000000..2d28a694cea5 --- /dev/null +++ b/filter/qa/unit/data/semi-transparent-line.odg 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) |