diff options
author | Xisco Fauli <xiscofauli@libreoffice.org> | 2023-08-12 02:28:02 +0200 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2023-08-12 10:00:29 +0200 |
commit | dcb3cb0bd4e4bf2bed05ae3b9d370e17a331a9b1 (patch) | |
tree | 08503b04609b8574c537b5db0470647e8e4f7b09 /svgio | |
parent | 0f3b36bd2749f360df84d1594c01e619ba0f4930 (diff) |
tdf#156616: check if character's parent has x or y
if so, only concatenate the characters that are in the same line
so the alignment will be calculated based on the
line's width
Change-Id: I704370c0a470f8b4cff97c51ad9863158118ee8a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155636
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Diffstat (limited to 'svgio')
-rw-r--r-- | svgio/inc/svgcharacternode.hxx | 4 | ||||
-rw-r--r-- | svgio/inc/svgtextnode.hxx | 7 | ||||
-rw-r--r-- | svgio/inc/svgtspannode.hxx | 7 | ||||
-rw-r--r-- | svgio/qa/cppunit/SvgImportTest.cxx | 38 | ||||
-rw-r--r-- | svgio/qa/cppunit/data/tdf156616.svg | 29 | ||||
-rw-r--r-- | svgio/source/svgreader/svgcharacternode.cxx | 8 | ||||
-rw-r--r-- | svgio/source/svgreader/svgdocumenthandler.cxx | 22 |
7 files changed, 99 insertions, 16 deletions
diff --git a/svgio/inc/svgcharacternode.hxx b/svgio/inc/svgcharacternode.hxx index 391c4029e46c..059aa9ece1fd 100644 --- a/svgio/inc/svgcharacternode.hxx +++ b/svgio/inc/svgcharacternode.hxx @@ -40,7 +40,7 @@ namespace svgio::svgreader // keep a copy of string data before space handling OUString maTextBeforeSpaceHandling; - SvgTextNode* mpTextParent; + SvgTspanNode* mpParentLine; /// local helpers rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> createSimpleTextPrimitive( @@ -68,7 +68,7 @@ namespace svgio::svgreader /// Text content const OUString& getText() const { return maText; } - void setTextParent(SvgTextNode* pTextParent) { mpTextParent = pTextParent; } + void setParentLine(SvgTspanNode* pParentLine) { mpParentLine = pParentLine; } }; } // end of namespace svgio::svgreader diff --git a/svgio/inc/svgtextnode.hxx b/svgio/inc/svgtextnode.hxx index 2d5f98ec18fc..787687977e11 100644 --- a/svgio/inc/svgtextnode.hxx +++ b/svgio/inc/svgtextnode.hxx @@ -33,10 +33,6 @@ namespace svgio::svgreader std::optional<basegfx::B2DHomMatrix> mpaTransform; - // The text line composed by the different SvgCharacterNode children - // it will be used to calculate their alignment - OUString maTextLine; - /// local helpers void DecomposeChild( const SvgNode& rCandidate, @@ -59,9 +55,6 @@ namespace svgio::svgreader /// transform content, set if found in current context const std::optional<basegfx::B2DHomMatrix>& getTransform() const { return mpaTransform; } void setTransform(const std::optional<basegfx::B2DHomMatrix>& pMatrix) { mpaTransform = pMatrix; } - - void concatenateTextLine(std::u16string_view rText) {maTextLine += rText;} - const OUString& getTextLine() const { return maTextLine; } }; } // end of namespace svgio::svgreader diff --git a/svgio/inc/svgtspannode.hxx b/svgio/inc/svgtspannode.hxx index d5d86c5a7c1a..92ed8319c628 100644 --- a/svgio/inc/svgtspannode.hxx +++ b/svgio/inc/svgtspannode.hxx @@ -39,6 +39,10 @@ namespace svgio::svgreader bool mbLengthAdjust : 1; // true = spacing, false = spacingAndGlyphs + // The text line composed by the different SvgCharacterNode children + // it will be used to calculate their alignment + OUString maTextLine; + public: SvgTspanNode( SVGToken aType, @@ -78,6 +82,9 @@ namespace svgio::svgreader /// LengthAdjust content bool getLengthAdjust() const { return mbLengthAdjust; } void setLengthAdjust(bool bNew) { mbLengthAdjust = bNew; } + + void concatenateTextLine(std::u16string_view rText) {maTextLine += rText;} + const OUString& getTextLine() const { return maTextLine; } }; } // end of namespace svgio::svgreader diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index cf66e5bb623f..d97892f8d98f 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -744,7 +744,45 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf85770) assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "text", " End"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "height", "11"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "familyname", "Times New Roman"); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf156616) +{ + Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/tdf156616.svg"); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength())); + + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(Primitive2DContainer(aSequence)); + + CPPUNIT_ASSERT (pDocument); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]", "text", "First"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]", "x", "114"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]", "y", "103"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "text", " line"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "x", "142"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "y", "103"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "text", "Second line"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "x", "114"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "y", "122"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]", "text", "First"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]", "x", "86"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]", "y", "153"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]", "text", " line"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]", "x", "114"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]", "y", "153"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]", "text", "Second line"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]", "x", "77"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]", "y", "172"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]", "text", "First"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]", "x", "59"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]", "y", "203"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[8]", "text", " line"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[8]", "x", "87"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[8]", "y", "203"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[9]", "text", "Second line"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[9]", "x", "40"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[9]", "y", "222"); } CPPUNIT_TEST_FIXTURE(Test, testTdf79163) diff --git a/svgio/qa/cppunit/data/tdf156616.svg b/svgio/qa/cppunit/data/tdf156616.svg new file mode 100644 index 000000000000..6b3bb3c6c6a5 --- /dev/null +++ b/svgio/qa/cppunit/data/tdf156616.svg @@ -0,0 +1,29 @@ +<svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg"> + <text + style="text-anchor:start" + x="114" + y="103"><tspan + x="114" + y="103"><tspan>First </tspan>line </tspan><tspan + x="114" + y="122">Second line</tspan> + </text> + <text + style="text-anchor:middle" + x="114" + y="153"><tspan + x="114" + y="153"><tspan>First </tspan>line </tspan><tspan + x="114" + y="172">Second line</tspan> + </text> + <text + style="text-anchor:end" + x="114" + y="203"><tspan + x="114" + y="203"><tspan>First </tspan>line </tspan><tspan + x="114" + y="222">Second line</tspan> + </text> +</svg> diff --git a/svgio/source/svgreader/svgcharacternode.cxx b/svgio/source/svgreader/svgcharacternode.cxx index 2b88944aa8d0..9ba70ffb3ef5 100644 --- a/svgio/source/svgreader/svgcharacternode.cxx +++ b/svgio/source/svgreader/svgcharacternode.cxx @@ -79,7 +79,7 @@ namespace svgio::svgreader OUString aText) : SvgNode(SVGToken::Character, rDocument, pParent), maText(std::move(aText)), - mpTextParent(nullptr) + mpParentLine(nullptr) { } @@ -251,7 +251,7 @@ namespace svgio::svgreader } // Use the whole text line to calculate the align position - double fWholeTextLineWidth(aTextLayouterDevice.getTextWidth(mpTextParent->getTextLine(), 0, mpTextParent->getTextLine().getLength())); + double fWholeTextLineWidth(aTextLayouterDevice.getTextWidth(mpParentLine->getTextLine(), 0, mpParentLine->getTextLine().getLength())); // apply TextAlign switch(aTextAlign) { @@ -482,6 +482,10 @@ namespace svgio::svgreader if(pPreviousCharacterNode->maTextBeforeSpaceHandling[nLastLength - 1] != ' ' && maTextBeforeSpaceHandling[0] != ' ') bAddGap = false; + // Do not add a gap if this node and last node are in different lines + if(pPreviousCharacterNode->mpParentLine != mpParentLine) + bAddGap = false; + // With this option a baseline shift between two char parts ('words') // will not add a space 'gap' to the end of the (non-last) word. This // seems to be the standard behaviour, see last bugdoc attached #122524# diff --git a/svgio/source/svgreader/svgdocumenthandler.cxx b/svgio/source/svgreader/svgdocumenthandler.cxx index 16f100e0b01e..ea70f3c5cbd6 100644 --- a/svgio/source/svgreader/svgdocumenthandler.cxx +++ b/svgio/source/svgreader/svgdocumenthandler.cxx @@ -62,7 +62,7 @@ namespace svgio::svgreader namespace { - svgio::svgreader::SvgCharacterNode* whiteSpaceHandling(svgio::svgreader::SvgNode const * pNode, svgio::svgreader::SvgTextNode* pText, svgio::svgreader::SvgCharacterNode* pLast) + svgio::svgreader::SvgCharacterNode* whiteSpaceHandling(svgio::svgreader::SvgNode const * pNode, svgio::svgreader::SvgTspanNode* pParentLine, svgio::svgreader::SvgCharacterNode* pLast) { if(pNode) { @@ -82,19 +82,31 @@ namespace // clean whitespace in text span svgio::svgreader::SvgCharacterNode* pCharNode = static_cast< svgio::svgreader::SvgCharacterNode* >(pCandidate); + pCharNode->setParentLine(pParentLine); + pCharNode->whiteSpaceHandling(); pLast = pCharNode->addGap(pLast); - pCharNode->setTextParent(pText); - pText->concatenateTextLine(pCharNode->getText()); + pParentLine->concatenateTextLine(pCharNode->getText()); break; } case SVGToken::Tspan: + { + svgio::svgreader::SvgTspanNode* pTspanNode = static_cast< svgio::svgreader::SvgTspanNode* >(pCandidate); + + // If x or y exist it means it's a new line of text + if(!pTspanNode->getX().empty() || !pTspanNode->getY().empty()) + pParentLine = pTspanNode; + + // recursively clean whitespaces in subhierarchy + pLast = whiteSpaceHandling(pCandidate, pParentLine, pLast); + break; + } case SVGToken::TextPath: case SVGToken::Tref: { // recursively clean whitespaces in subhierarchy - pLast = whiteSpaceHandling(pCandidate, pText, pLast); + pLast = whiteSpaceHandling(pCandidate, pParentLine, pLast); break; } default: @@ -480,7 +492,7 @@ namespace if(pTextNode) { // cleanup read strings - whiteSpaceHandling(pTextNode, static_cast< SvgTextNode*>(pTextNode), nullptr); + whiteSpaceHandling(pTextNode, static_cast< SvgTspanNode*>(pTextNode), nullptr); } } |