summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-11-11 15:58:11 +0100
committerMiklos Vajna <vmiklos@collabora.com>2022-11-15 15:04:37 +0100
commit158628777ed9a18ac8f9ec5e0795f381637da8c7 (patch)
treecfb3ec3ac0b8cda6c4f72e350af3c08023d39dfa
parent12269c021e785b8dca7e57a378d02023f7863d62 (diff)
SVG export: fix handling of semi-transparent, multi-para shape text
The bugdoc had a shape with two paragraphs. The export of the second paragraph went wrong: the position & size of the text was larger than expected. This problem was specific to semi-transparent text. SVGTextWriter::setTextPosition() is recursive in this case. The non-transparent case left nCurAction unchanged in the outer setTextPosition() and it returned 1 ("text is found"). The semi-transparent case changed nCurAction by +2 and returned 0 ("text is not found"). This led to all sorts of trouble, including mismatching Push() and Pop() calls on the output device when replaying the metafile. Fix the problem by routing the empty state from the inner setTextPosition() to the outer one: if we return 1 ("text is found"), then we know that the state is non-empty. Once the empty state is correct in the outer setTextPosition(), then even the transparent case also leaves nCurAction unchanged and the whole shape text has the correct position and size. I forgot to update this empty state in ther outer setTextPosition() in commit 666f252457bdb4371d15380a0289e107b2dfbe84 (SVG export: fix lost semi-transparent text on shapes, 2020-07-17). (cherry picked from commit c725028f15c36fc626d9ad8cdc288eb73c3e2643) Conflicts: filter/qa/unit/svg.cxx Change-Id: I7dc93fe13c4510220bf09a388e742799ed042510
-rw-r--r--filter/qa/unit/data/semi-transparent-multi-para.odgbin0 -> 10299 bytes
-rw-r--r--filter/qa/unit/svg.cxx29
-rw-r--r--filter/source/svg/svgwriter.cxx5
3 files changed, 34 insertions, 0 deletions
diff --git a/filter/qa/unit/data/semi-transparent-multi-para.odg b/filter/qa/unit/data/semi-transparent-multi-para.odg
new file mode 100644
index 000000000000..5e01e31e4f7f
--- /dev/null
+++ b/filter/qa/unit/data/semi-transparent-multi-para.odg
Binary files differ
diff --git a/filter/qa/unit/svg.cxx b/filter/qa/unit/svg.cxx
index 5dcb1af0eb90..070225b1491d 100644
--- a/filter/qa/unit/svg.cxx
+++ b/filter/qa/unit/svg.cxx
@@ -14,6 +14,10 @@
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/frame/XStorable.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+
#include <unotools/streamwrap.hxx>
#include <unotools/mediadescriptor.hxx>
#include <tools/stream.hxx>
@@ -160,6 +164,31 @@ CPPUNIT_TEST_FIXTURE(SvgFilterTest, testSemiTransparentText)
assertXPath(pXmlDoc, "//svg:text[2]/svg:tspan/svg:tspan/svg:tspan[@fill-opacity]", 0);
}
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testSemiTransparentMultiParaText)
+{
+ // Given a shape with semi-transparent, multi-paragraph text:
+ load(u"semi-transparent-multi-para.odg");
+
+ // When exporting 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);
+
+ // Then make sure that the two semi-tranparent paragraphs have the same X position:
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+ assertXPath(pXmlDoc, "(//svg:tspan[@class='TextPosition'])[1]", "x", "5908");
+ assertXPath(pXmlDoc, "(//svg:tspan[@class='TextPosition'])[1]/svg:tspan", "fill-opacity",
+ "0.8");
+ assertXPath(pXmlDoc, "(//svg:tspan[@class='TextPosition'])[2]", "x", "5908");
+ assertXPath(pXmlDoc, "(//svg:tspan[@class='TextPosition'])[2]/svg:tspan", "fill-opacity",
+ "0.8");
+}
+
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 3e54df31ba49..c3abf3420877 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -640,6 +640,11 @@ sal_Int32 SVGTextWriter::setTextPosition(const GDIMetaFile& rMtf, sal_uLong& nCu
{
// Text is found in the inner metafile.
bConfigured = true;
+
+ // nTextFound == 1 is only possible if the inner setTextPosition() had bEmpty ==
+ // false, adjust our bEmpty accordingly.
+ bEmpty = false;
+
mrActionWriter.StartMask(pA->GetPoint(), pA->GetSize(), pA->GetGradient(),
nWriteFlags, &maTextOpacity);
}