diff options
author | Xisco Fauli <xiscofauli@libreoffice.org> | 2023-08-14 14:52:41 +0200 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2023-08-15 03:53:06 +0200 |
commit | 5cfd31e505b4d1b4f9d2e21b0f9f8aac22539f47 (patch) | |
tree | b037f5d6ce2cfc412a75382db71a55249ba49b0c /svgio | |
parent | 850b66f969834e61f3cb1a1ccd4bfc15f23d558f (diff) |
tdf#93583: use getTextWidth to calculate line's width
Since every character in the line might use different styles
Change-Id: I2ce079d4308f4acde42a8366838749a7c20331b4
Change-Id: I01f51f157caa667cebc8860ae37d4458fac2d511
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155666
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/svgtspannode.hxx | 8 | ||||
-rw-r--r-- | svgio/qa/cppunit/SvgImportTest.cxx | 27 | ||||
-rw-r--r-- | svgio/qa/cppunit/data/tdf93583.svg | 7 | ||||
-rw-r--r-- | svgio/source/svgreader/svgcharacternode.cxx | 70 | ||||
-rw-r--r-- | svgio/source/svgreader/svgdocumenthandler.cxx | 24 | ||||
-rw-r--r-- | svgio/source/svgreader/svgtspannode.cxx | 3 |
7 files changed, 104 insertions, 39 deletions
diff --git a/svgio/inc/svgcharacternode.hxx b/svgio/inc/svgcharacternode.hxx index 059aa9ece1fd..d81066af47a6 100644 --- a/svgio/inc/svgcharacternode.hxx +++ b/svgio/inc/svgcharacternode.hxx @@ -24,6 +24,7 @@ #include <string_view> +#include <drawinglayer/attribute/fontattribute.hxx> #include "svgtextnode.hxx" #include "svgtextposition.hxx" @@ -58,6 +59,9 @@ namespace svgio::svgreader OUString aText); virtual ~SvgCharacterNode() override; + static drawinglayer::attribute::FontAttribute getFontAttribute( + const SvgStyleAttributes& rSvgStyleAttributes); + virtual const SvgStyleAttributes* getSvgStyleAttributes() const override; void decomposeText(drawinglayer::primitive2d::Primitive2DContainer& rTarget, SvgTextPosition& rSvgTextPosition) const; diff --git a/svgio/inc/svgtspannode.hxx b/svgio/inc/svgtspannode.hxx index 92ed8319c628..991b0ac451f6 100644 --- a/svgio/inc/svgtspannode.hxx +++ b/svgio/inc/svgtspannode.hxx @@ -39,9 +39,9 @@ namespace svgio::svgreader bool mbLengthAdjust : 1; // true = spacing, false = spacingAndGlyphs - // The text line composed by the different SvgCharacterNode children + // The text line width composed by the different SvgCharacterNode children // it will be used to calculate their alignment - OUString maTextLine; + double mnTextLineWidth; public: SvgTspanNode( @@ -83,8 +83,8 @@ namespace svgio::svgreader 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; } + void concatenateTextLineWidth(double nWidth) {mnTextLineWidth += nWidth;} + double getTextLineWith() const { return mnTextLineWidth; } }; } // end of namespace svgio::svgreader diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index d97892f8d98f..53f6b23da4fd 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -746,6 +746,33 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf85770) assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "familyname", "Times New Roman"); } +CPPUNIT_TEST_FIXTURE(Test, testTdf93583) +{ + Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/tdf93583.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", "This is the"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]", "x", "62"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]", "y", "303"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]", "width", "16"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]", "height", "16"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "text", " first"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "x", "127"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "y", "303"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "width", "32"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "height", "32"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "text", " line"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "x", "187"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "y", "303"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "width", "16"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "height", "16"); +} + CPPUNIT_TEST_FIXTURE(Test, testTdf156616) { Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/tdf156616.svg"); diff --git a/svgio/qa/cppunit/data/tdf93583.svg b/svgio/qa/cppunit/data/tdf93583.svg new file mode 100644 index 000000000000..13e63e677ffb --- /dev/null +++ b/svgio/qa/cppunit/data/tdf93583.svg @@ -0,0 +1,7 @@ +<svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg"> + <text + style="text-anchor:end" + x="214" + y="303"><tspan>This is the<tspan style="font-size:200%"> first </tspan>line</tspan> + </text> +</svg> diff --git a/svgio/source/svgreader/svgcharacternode.cxx b/svgio/source/svgreader/svgcharacternode.cxx index 9ba70ffb3ef5..ebc317c3a445 100644 --- a/svgio/source/svgreader/svgcharacternode.cxx +++ b/svgio/source/svgreader/svgcharacternode.cxx @@ -19,7 +19,6 @@ #include <svgcharacternode.hxx> #include <svgstyleattributes.hxx> -#include <drawinglayer/attribute/fontattribute.hxx> #include <drawinglayer/primitive2d/textprimitive2d.hxx> #include <drawinglayer/primitive2d/textlayoutdevice.hxx> #include <drawinglayer/primitive2d/textbreakuphelper.hxx> @@ -100,6 +99,39 @@ namespace svgio::svgreader } } + drawinglayer::attribute::FontAttribute SvgCharacterNode::getFontAttribute( + const SvgStyleAttributes& rSvgStyleAttributes) + { + const SvgStringVector& rFontFamilyVector = rSvgStyleAttributes.getFontFamily(); + OUString aFontFamily("Times New Roman"); + if(!rFontFamilyVector.empty()) + aFontFamily=rFontFamilyVector[0]; + + // #i122324# if the FontFamily name ends on ' embedded' it is probably a re-import + // of a SVG export with font embedding. Remove this to make font matching work. This + // is pretty safe since there should be no font family names ending on ' embedded'. + // Remove again when FontEmbedding is implemented in SVG import + if(aFontFamily.endsWith(" embedded")) + { + aFontFamily = aFontFamily.copy(0, aFontFamily.getLength() - 9); + } + + const ::FontWeight nFontWeight(getVclFontWeight(rSvgStyleAttributes.getFontWeight())); + bool bItalic(FontStyle::italic == rSvgStyleAttributes.getFontStyle() || FontStyle::oblique == rSvgStyleAttributes.getFontStyle()); + + return drawinglayer::attribute::FontAttribute( + aFontFamily, + OUString(), + nFontWeight, + false/*bSymbol*/, + false/*bVertical*/, + bItalic, + false/*bMonospaced*/, + false/*bOutline*/, + false/*bRTL*/, + false/*bBiDiStrong*/); + } + rtl::Reference<BasePrimitive2D> SvgCharacterNode::createSimpleTextPrimitive( SvgTextPosition& rSvgTextPosition, const SvgStyleAttributes& rSvgStyleAttributes) const @@ -111,35 +143,9 @@ namespace svgio::svgreader if(nLength) { sal_uInt32 nIndex(0); - // prepare FontAttribute - const SvgStringVector& rFontFamilyVector = rSvgStyleAttributes.getFontFamily(); - OUString aFontFamily("Times New Roman"); - if(!rFontFamilyVector.empty()) - aFontFamily=rFontFamilyVector[0]; - - // #i122324# if the FontFamily name ends on ' embedded' it is probably a re-import - // of a SVG export with font embedding. Remove this to make font matching work. This - // is pretty safe since there should be no font family names ending on ' embedded'. - // Remove again when FontEmbedding is implemented in SVG import - if(aFontFamily.endsWith(" embedded")) - { - aFontFamily = aFontFamily.copy(0, aFontFamily.getLength() - 9); - } - const ::FontWeight nFontWeight(getVclFontWeight(rSvgStyleAttributes.getFontWeight())); - bool bItalic(FontStyle::italic == rSvgStyleAttributes.getFontStyle() || FontStyle::oblique == rSvgStyleAttributes.getFontStyle()); - - const drawinglayer::attribute::FontAttribute aFontAttribute( - aFontFamily, - OUString(), - nFontWeight, - false/*bSymbol*/, - false/*bVertical*/, - bItalic, - false/*bMonospaced*/, - false/*bOutline*/, - false/*bRTL*/, - false/*bBiDiStrong*/); + // prepare FontAttribute + const drawinglayer::attribute::FontAttribute aFontAttribute(getFontAttribute(rSvgStyleAttributes)); // prepare FontSizeNumber double fFontWidth(rSvgStyleAttributes.getFontSizeNumber().solve(*this)); @@ -250,19 +256,17 @@ namespace svgio::svgreader } } - // Use the whole text line to calculate the align position - double fWholeTextLineWidth(aTextLayouterDevice.getTextWidth(mpParentLine->getTextLine(), 0, mpParentLine->getTextLine().getLength())); // apply TextAlign switch(aTextAlign) { case TextAlign::right: { - aPosition.setX(aPosition.getX() - fWholeTextLineWidth); + aPosition.setX(aPosition.getX() - mpParentLine->getTextLineWith()); break; } case TextAlign::center: { - aPosition.setX(aPosition.getX() - (fWholeTextLineWidth * 0.5)); + aPosition.setX(aPosition.getX() - (mpParentLine->getTextLineWith() * 0.5)); break; } case TextAlign::notset: diff --git a/svgio/source/svgreader/svgdocumenthandler.cxx b/svgio/source/svgreader/svgdocumenthandler.cxx index ea70f3c5cbd6..0b66a4bb44da 100644 --- a/svgio/source/svgreader/svgdocumenthandler.cxx +++ b/svgio/source/svgreader/svgdocumenthandler.cxx @@ -55,6 +55,9 @@ #include <sal/log.hxx> #include <osl/diagnose.h> +#include <com/sun/star/lang/Locale.hpp> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> + using namespace com::sun::star; namespace svgio::svgreader @@ -87,7 +90,26 @@ namespace pCharNode->whiteSpaceHandling(); pLast = pCharNode->addGap(pLast); - pParentLine->concatenateTextLine(pCharNode->getText()); + double fTextWidth(0.0); + + const SvgStyleAttributes* pSvgStyleAttributes = pCharNode->getSvgStyleAttributes(); + + if(pSvgStyleAttributes) + { + const drawinglayer::attribute::FontAttribute aFontAttribute( + svgio::svgreader::SvgCharacterNode::getFontAttribute(*pSvgStyleAttributes)); + + double fFontWidth(pSvgStyleAttributes->getFontSizeNumber().solve(*pCharNode)); + double fFontHeight(fFontWidth); + + css::lang::Locale aLocale; + + drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; + aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth, fFontHeight, aLocale); + fTextWidth = aTextLayouterDevice.getTextWidth(pCharNode->getText(), 0.0, pCharNode->getText().getLength()); + } + + pParentLine->concatenateTextLineWidth(fTextWidth); break; } case SVGToken::Tspan: diff --git a/svgio/source/svgreader/svgtspannode.cxx b/svgio/source/svgreader/svgtspannode.cxx index 4472b88ab3ad..2ac7ee1118ed 100644 --- a/svgio/source/svgreader/svgtspannode.cxx +++ b/svgio/source/svgreader/svgtspannode.cxx @@ -28,7 +28,8 @@ namespace svgio::svgreader SvgNode* pParent) : SvgNode(aType, rDocument, pParent), maSvgStyleAttributes(*this), - mbLengthAdjust(true) + mbLengthAdjust(true), + mnTextLineWidth(0.0) { } |