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>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -188,7 +188,8 @@ namespace svgio::svgreader
|
||||
|
||||
// text tokens
|
||||
Text,
|
||||
BaselineShift
|
||||
BaselineShift,
|
||||
DominantBaseline
|
||||
};
|
||||
|
||||
SVGToken StrToSVGToken(const OUString& rStr, bool bCaseIndependent);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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>
|
||||
|
After Width: | Height: | Size: 377 B |
@@ -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());
|
||||
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user