summaryrefslogtreecommitdiff
path: root/svgio
diff options
context:
space:
mode:
authorXisco Fauli <xiscofauli@libreoffice.org>2023-08-21 12:35:49 +0200
committerXisco Fauli <xiscofauli@libreoffice.org>2023-08-21 19:59:27 +0200
commit8fa209ce2e800dc8a51e941cd42a65fa8b2eb14b (patch)
tree2501cf959b05ac8bcf909932f0980b7fe249f3b8 /svgio
parente6a5ccbe578898878468180c2d4c9ee9e6afbad9 (diff)
tdf#156834: Add basic support for dominant-baseline attribute
Change-Id: I005d6ca6bc340d73cae639ccd09321a0a00bc4b7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155892 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Diffstat (limited to 'svgio')
-rw-r--r--svgio/inc/svgstyleattributes.hxx13
-rw-r--r--svgio/inc/svgtoken.hxx3
-rw-r--r--svgio/qa/cppunit/SvgImportTest.cxx24
-rw-r--r--svgio/qa/cppunit/data/tdf156834.svg7
-rw-r--r--svgio/source/svgreader/svgcharacternode.cxx24
-rw-r--r--svgio/source/svgreader/svgstyleattributes.cxx43
-rw-r--r--svgio/source/svgreader/svgtoken.cxx6
7 files changed, 116 insertions, 4 deletions
diff --git a/svgio/inc/svgstyleattributes.hxx b/svgio/inc/svgstyleattributes.hxx
index 751ee6014e41..60781942667b 100644
--- a/svgio/inc/svgstyleattributes.hxx
+++ b/svgio/inc/svgstyleattributes.hxx
@@ -162,6 +162,13 @@ namespace svgio::svgreader
Length
};
+ enum class DominantBaseline
+ {
+ Auto,
+ Middle,
+ Hanging
+ };
+
enum class Visibility
{
notset,
@@ -223,6 +230,8 @@ namespace svgio::svgreader
BaselineShift maBaselineShift;
SvgNumber maBaselineShiftNumber;
+ DominantBaseline maDominantBaseline;
+
mutable std::vector<sal_uInt16> maResolvingParent;
// defines if this attributes are part of a ClipPath. If yes,
@@ -438,6 +447,10 @@ namespace svgio::svgreader
void setBaselineShift(const BaselineShift aBaselineShift) { maBaselineShift = aBaselineShift; }
BaselineShift getBaselineShift() const;
SvgNumber getBaselineShiftNumber() const;
+
+ // DominantBaseline
+ void setDominantBaseline(const DominantBaseline aDominantBaseline) { maDominantBaseline = aDominantBaseline; }
+ DominantBaseline getDominantBaseline() const;
};
} // end of namespace svgio::svgreader
diff --git a/svgio/inc/svgtoken.hxx b/svgio/inc/svgtoken.hxx
index 6c1a17692f22..3a4a89f285e2 100644
--- a/svgio/inc/svgtoken.hxx
+++ b/svgio/inc/svgtoken.hxx
@@ -188,7 +188,8 @@ namespace svgio::svgreader
// text tokens
Text,
- BaselineShift
+ BaselineShift,
+ DominantBaseline
};
SVGToken StrToSVGToken(const OUString& rStr, bool bCaseIndependent);
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx
index 95cbc0bcda6a..4d7cd9772d51 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -731,6 +731,30 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf156777)
assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]", "y", "23");
}
+CPPUNIT_TEST_FIXTURE(Test, testTdf156834)
+{
+ Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/tdf156834.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", 3);
+ assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]", "text", "Auto");
+ assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]", "x", "30");
+ assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]", "y", "20");
+
+ assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "text", "Middle");
+ assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "x", "30");
+ assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]", "y", "56");
+
+ assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "text", "Hanging");
+ assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "x", "30");
+ assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]", "y", "94");
+}
+
CPPUNIT_TEST_FIXTURE(Test, testTdf104339)
{
Primitive2DSequence aSequenceTdf104339 = parseSvg(u"/svgio/qa/cppunit/data/tdf104339.svg");
diff --git a/svgio/qa/cppunit/data/tdf156834.svg b/svgio/qa/cppunit/data/tdf156834.svg
new file mode 100644
index 000000000000..74dc1548186e
--- /dev/null
+++ b/svgio/qa/cppunit/data/tdf156834.svg
@@ -0,0 +1,7 @@
+<svg viewBox="0 0 200 120" xmlns="http://www.w3.org/2000/svg">
+ <path d="M20,20 L180,20 M20,50 L180,50 M20,80 L180,80" stroke="grey" />
+
+ <text dominant-baseline="auto" x="30" y="20" font-size="20">Auto</text>
+ <text dominant-baseline="middle" x="30" y="50" font-size="20">Middle</text>
+ <text dominant-baseline="Hanging" x="30" y="80" font-size="20">Hanging</text>
+</svg>
diff --git a/svgio/source/svgreader/svgcharacternode.cxx b/svgio/source/svgreader/svgcharacternode.cxx
index 9b9e87d23dca..0199a1ff9105 100644
--- a/svgio/source/svgreader/svgcharacternode.cxx
+++ b/svgio/source/svgreader/svgcharacternode.cxx
@@ -279,6 +279,30 @@ namespace svgio::svgreader
}
}
+ // get DominantBaseline
+ const DominantBaseline aDominantBaseline(rSvgStyleAttributes.getDominantBaseline());
+
+ basegfx::B2DRange aRange(aTextLayouterDevice.getTextBoundRect(getText(), nIndex, nLength));
+ // apply DominantBaseline
+ switch(aDominantBaseline)
+ {
+ case DominantBaseline::Middle:
+ {
+ aPosition.setY(aPosition.getY() - aRange.getCenterY());
+ break;
+ }
+ case DominantBaseline::Hanging:
+ {
+ aPosition.setY(aPosition.getY() - aRange.getMinY());
+ break;
+ }
+ default: // DominantBaseline::Auto
+ {
+ // nothing to do
+ break;
+ }
+ }
+
// get BaselineShift
const BaselineShift aBaselineShift(rSvgStyleAttributes.getBaselineShift());
diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx
index 68e8b59d76c2..4ed60d297e4f 100644
--- a/svgio/source/svgreader/svgstyleattributes.cxx
+++ b/svgio/source/svgreader/svgstyleattributes.cxx
@@ -1285,7 +1285,8 @@ namespace svgio::svgreader
maClipRule(FillRule::notset),
maBaselineShift(BaselineShift::Baseline),
maBaselineShiftNumber(0),
- maResolvingParent(30, 0),
+ maDominantBaseline(DominantBaseline::Auto),
+ maResolvingParent(31, 0),
mbIsClipPathContent(SVGToken::ClipPathNode == mrOwner.getType()),
mbStrokeDasharraySet(false)
{
@@ -1957,6 +1958,26 @@ namespace svgio::svgreader
}
break;
}
+ case SVGToken::DominantBaseline:
+ {
+ if(!aContent.isEmpty())
+ {
+ if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"middle"))
+ {
+ setDominantBaseline(DominantBaseline::Middle);
+ }
+ else if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"hanging"))
+ {
+ setDominantBaseline(DominantBaseline::Hanging);
+ }
+ else
+ {
+ // no DominantBaseline
+ setDominantBaseline(DominantBaseline::Auto);
+ }
+ }
+ break;
+ }
default:
{
break;
@@ -3082,6 +3103,26 @@ namespace svgio::svgreader
return BaselineShift::Baseline;
}
+
+ DominantBaseline SvgStyleAttributes::getDominantBaseline() const
+ {
+ if(maDominantBaseline != DominantBaseline::Auto)
+ {
+ return maDominantBaseline;
+ }
+
+ const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+ if (pSvgStyleAttributes && maResolvingParent[30] < nStyleDepthLimit)
+ {
+ ++maResolvingParent[30];
+ auto ret = pSvgStyleAttributes->getDominantBaseline();
+ --maResolvingParent[30];
+ return ret;
+ }
+
+ return DominantBaseline::Auto;
+ }
} // end of namespace svgio
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svgio/source/svgreader/svgtoken.cxx b/svgio/source/svgreader/svgtoken.cxx
index 961c4ec3b5a4..492c78623f14 100644
--- a/svgio/source/svgreader/svgtoken.cxx
+++ b/svgio/source/svgreader/svgtoken.cxx
@@ -177,7 +177,8 @@ constexpr auto aSVGTokenMapperList = frozen::make_unordered_map<std::u16string_v
{ u"stroke-width", SVGToken::StrokeWidth },
{ u"text", SVGToken::Text },
- { u"baseline-shift", SVGToken::BaselineShift }
+ { u"baseline-shift", SVGToken::BaselineShift },
+ { u"dominant-baseline", SVGToken::DominantBaseline }
});
// The same elements as the map above but lowercase. CSS is case insensitive
@@ -334,7 +335,8 @@ constexpr auto aSVGLowerCaseTokenMapperList = frozen::make_unordered_map<std::u
{ u"stroke-width", SVGToken::StrokeWidth },
{ u"text", SVGToken::Text },
- { u"baseline-shift", SVGToken::BaselineShift }
+ { u"baseline-shift", SVGToken::BaselineShift },
+ { u"dominant-baseline", SVGToken::DominantBaseline }
});
static_assert(sizeof(aSVGTokenMapperList) == sizeof(aSVGLowerCaseTokenMapperList),