diff options
author | Xisco Fauli <xiscofauli@libreoffice.org> | 2024-01-26 15:10:58 +0100 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2024-01-26 19:31:03 +0100 |
commit | e7186b49a9a0b24ddc3b1c5384b5d9facb03518c (patch) | |
tree | cb8fcb1e001d42b75599f31430558e471e7a7c3a /svgio | |
parent | 80480fb5ecc18a0a9b6c4cccc5cc35eba721f636 (diff) |
tdf#158445: support viewBox in symbol elements
Change-Id: Ie45b1e1dd4a4dcfc3cf3ce3d30f8dd9e040e37fb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162605
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Diffstat (limited to 'svgio')
-rw-r--r-- | svgio/inc/svgsymbolnode.hxx | 15 | ||||
-rw-r--r-- | svgio/qa/cppunit/SvgImportTest.cxx | 15 | ||||
-rw-r--r-- | svgio/qa/cppunit/data/tdf158445.svg | 5 | ||||
-rw-r--r-- | svgio/source/svgreader/svgsymbolnode.cxx | 94 |
4 files changed, 128 insertions, 1 deletions
diff --git a/svgio/inc/svgsymbolnode.hxx b/svgio/inc/svgsymbolnode.hxx index 7a19b335b7b5..e82f75a7671c 100644 --- a/svgio/inc/svgsymbolnode.hxx +++ b/svgio/inc/svgsymbolnode.hxx @@ -29,6 +29,12 @@ namespace svgio::svgreader /// use styles SvgStyleAttributes maSvgStyleAttributes; + SvgNumber maX; + SvgNumber maY; + SvgNumber maWidth; + SvgNumber maHeight; + + std::unique_ptr<basegfx::B2DRange> mpViewBox; SvgAspectRatio maSvgAspectRatio; public: @@ -39,6 +45,15 @@ namespace svgio::svgreader virtual const SvgStyleAttributes* getSvgStyleAttributes() const override; virtual void parseAttribute(SVGToken aSVGToken, const OUString& aContent) override; + virtual void decomposeSvgNode(drawinglayer::primitive2d::Primitive2DContainer& rTarget, bool bReferenced) const override; + + /// viewBox content + const basegfx::B2DRange* getViewBox() const { return mpViewBox.get(); } + void setViewBox(const basegfx::B2DRange* pViewBox) { mpViewBox.reset(); if(pViewBox) mpViewBox.reset( new basegfx::B2DRange(*pViewBox) ); } + + /// SvgAspectRatio content + const SvgAspectRatio& getSvgAspectRatio() const { return maSvgAspectRatio; } + }; } // end of namespace svgio::svgreader diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index 1b0be44177fe..d99e56bfef35 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -1591,6 +1591,21 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf155733) assertXPath(pDocument, "/primitive2D/transform/transform/unifiedtransparence"_ostr, "transparence"_ostr, "50"); } +CPPUNIT_TEST_FIXTURE(Test, testTdf158445) +{ + Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/tdf158445.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/transform/transform/transform/polypolygoncolor"_ostr, "color"_ostr, "#000000"); + assertXPath(pDocument, "/primitive2D/transform/transform/transform/transform/polypolygoncolor/polypolygon"_ostr, "height"_ostr, "8.052"); + assertXPath(pDocument, "/primitive2D/transform/transform/transform/transform/polypolygoncolor/polypolygon"_ostr, "width"_ostr, "5.328"); +} + CPPUNIT_TEST_FIXTURE(Test, testTdf97663) { Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/em_units.svg"); diff --git a/svgio/qa/cppunit/data/tdf158445.svg b/svgio/qa/cppunit/data/tdf158445.svg new file mode 100644 index 000000000000..20e084dd05e5 --- /dev/null +++ b/svgio/qa/cppunit/data/tdf158445.svg @@ -0,0 +1,5 @@ +<svg width="160.353" height="30.488" xmlns="http://www.w3.org/2000/svg" viewBox="-0.376 -26.625 160.353 30.488"> +<symbol id="STIXTwoMathRegular_4275" width="5.868" height="51.216" viewBox="0 -31.524 5.868 51.216"> +<path d="M 5.868 -2.088 L 5.868 -2.088 L 5.46 0 L 0.54 0 L 0.54 -0.588 L 2.244 -2.316 Q 2.916 -2.988 3.354 -3.504 Q 3.792 -4.02 4.008 -4.542 Q 4.224 -5.064 4.224 -5.736 Q 4.224 -6.372 3.834 -6.786 Q 3.444 -7.2 2.736 -7.2 Q 2.088 -7.2 1.65 -6.942 Q 1.212 -6.684 0.876 -6.096 L 0.552 -6.252 Q 0.852 -7.092 1.482 -7.572 Q 2.112 -8.052 3.036 -8.052 Q 3.756 -8.052 4.308 -7.794 Q 4.86 -7.536 5.172 -7.056 Q 5.484 -6.576 5.484 -5.892 Q 5.484 -5.304 5.22 -4.788 Q 4.956 -4.272 4.47 -3.732 Q 3.984 -3.192 3.312 -2.532 L 1.812 -1.08 L 1.812 -0.996 L 2.748 -1.044 L 4.308 -1.044 Q 4.656 -1.044 4.842 -1.14 Q 5.028 -1.236 5.16 -1.47 Q 5.292 -1.704 5.448 -2.088 Z " viewBox="0 -31.524 5.868 51.216"/> +</symbol> +<use href="#STIXTwoMathRegular_4275" transform="translate(151.174 -52.774) scale(1.4)" fill="black" /></svg> diff --git a/svgio/source/svgreader/svgsymbolnode.cxx b/svgio/source/svgreader/svgsymbolnode.cxx index 6e18d4bca049..f86dd27bb3a0 100644 --- a/svgio/source/svgreader/svgsymbolnode.cxx +++ b/svgio/source/svgreader/svgsymbolnode.cxx @@ -18,6 +18,8 @@ */ #include <svgsymbolnode.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> namespace svgio::svgreader { @@ -54,9 +56,60 @@ namespace svgio::svgreader readLocalCssStyle(aContent); break; } + case SVGToken::X: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + maX = aNum; + } + break; + } + case SVGToken::Y: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + maY = aNum; + } + break; + } + case SVGToken::Width: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + maWidth = aNum; + } + } + break; + } + case SVGToken::Height: + { + SvgNumber aNum; + + if(readSingleNumber(aContent, aNum)) + { + if(aNum.isPositive()) + { + maHeight = aNum; + } + } + break; + } case SVGToken::ViewBox: { - readViewBox(aContent, *this); + const basegfx::B2DRange aRange(readViewBox(aContent, *this)); + + if(!aRange.isEmpty()) + { + setViewBox(&aRange); + } break; } case SVGToken::PreserveAspectRatio: @@ -71,6 +124,45 @@ namespace svgio::svgreader } } + void SvgSymbolNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DContainer& rTarget, bool bReferenced) const + { + drawinglayer::primitive2d::Primitive2DContainer aNewTarget; + + // decompose children + SvgNode::decomposeSvgNode(aNewTarget, bReferenced); + + if(aNewTarget.empty()) + return; + + if(getViewBox()) + { + // create mapping + // #i122610 SVG 1.1 defines in section 5.1.2 that if the attribute preserveAspectRatio is not specified, + // then the effect is as if a value of 'xMidYMid meet' were specified. + SvgAspectRatio aRatioDefault(SvgAlign::xMidYMid, true); + const SvgAspectRatio& rRatio = getSvgAspectRatio().isSet()? getSvgAspectRatio() : aRatioDefault; + + const double fX(maX.solve(*this, NumberType::xcoordinate)); + const double fY(maY.solve(*this, NumberType::ycoordinate)); + const double fWidth(maWidth.solve(*this, NumberType::xcoordinate)); + const double fHeight(maHeight.solve(*this, NumberType::ycoordinate)); + const basegfx::B2DRange aRange(fX, fY, fX + fWidth, fY + fHeight); + + // let mapping be created from SvgAspectRatio + const basegfx::B2DHomMatrix aEmbeddingTransform( + rRatio.createMapping(aRange, *getViewBox())); + + // prepare embedding in transformation + // create embedding group element with transformation + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::TransformPrimitive2D( + aEmbeddingTransform, + std::move(aNewTarget))); + + rTarget.push_back(xRef); + } + } + } // end of namespace svgio::svgreader /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |