summaryrefslogtreecommitdiff
path: root/svgio
diff options
context:
space:
mode:
authorXisco Fauli <xiscofauli@libreoffice.org>2023-08-14 14:52:41 +0200
committerXisco Fauli <xiscofauli@libreoffice.org>2023-08-15 03:53:06 +0200
commit5cfd31e505b4d1b4f9d2e21b0f9f8aac22539f47 (patch)
treeb037f5d6ce2cfc412a75382db71a55249ba49b0c /svgio
parent850b66f969834e61f3cb1a1ccd4bfc15f23d558f (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.hxx4
-rw-r--r--svgio/inc/svgtspannode.hxx8
-rw-r--r--svgio/qa/cppunit/SvgImportTest.cxx27
-rw-r--r--svgio/qa/cppunit/data/tdf93583.svg7
-rw-r--r--svgio/source/svgreader/svgcharacternode.cxx70
-rw-r--r--svgio/source/svgreader/svgdocumenthandler.cxx24
-rw-r--r--svgio/source/svgreader/svgtspannode.cxx3
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)
{
}