diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-01-17 11:47:14 +0100 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2022-01-18 08:20:36 +0100 |
commit | 38da870731123d8ad97b62f95c61ec8c1257d9a9 (patch) | |
tree | ed73ce06e2e9c15d237d91d0a6ee89a694ce88dd /filter | |
parent | 242d2752aa6af2c52affc90e84b58c59c5fa779d (diff) |
SVG export: fix missing custom bullets
It seems this was broken since b76628acb1ae4fc06f8c1b70ec2e0cf39356deef
(text export support for bullets and hyperlinks, 2012-08-11), the
problem is that SVGFilter::implEmbedBulletGlyphs() has a fixed list of
characters that are typically used as bullets, but e.g. "-" is missing
from that list.
Fix this by improving SVGTextWriter::implWriteBulletChars() to continue
working from those shared glyph paths when the glyph is in the fixed
list, but otherwise call GetTextOutline() to look up the path for the
custom bullet.
(cherry picked from commit bbc4360b5beb012adf1e2652328d3e18d66224aa)
Change-Id: I3de8fab8dc6c78e273629d13566d1f9f289eb752
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128501
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'filter')
-rw-r--r-- | filter/qa/unit/data/custom-bullet.fodp | 36 | ||||
-rw-r--r-- | filter/qa/unit/svg.cxx | 27 | ||||
-rw-r--r-- | filter/source/svg/svgexport.cxx | 12 | ||||
-rw-r--r-- | filter/source/svg/svgfilter.hxx | 4 | ||||
-rw-r--r-- | filter/source/svg/svgwriter.cxx | 24 | ||||
-rw-r--r-- | filter/source/svg/svgwriter.hxx | 2 |
6 files changed, 100 insertions, 5 deletions
diff --git a/filter/qa/unit/data/custom-bullet.fodp b/filter/qa/unit/data/custom-bullet.fodp new file mode 100644 index 000000000000..4139260f9780 --- /dev/null +++ b/filter/qa/unit/data/custom-bullet.fodp @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<office:document xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.presentation"> + <office:automatic-styles> + <style:page-layout style:name="PM1"> + <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="28cm" fo:page-height="15.75cm" style:print-orientation="landscape"/> + </style:page-layout> + <style:style style:name="gr1" style:family="graphic" style:parent-style-name="standard"> + <style:graphic-properties draw:stroke="none" svg:stroke-color="#000000" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="true" draw:auto-grow-width="false" fo:max-height="0cm" fo:min-height="0cm"/> + </style:style> + <text:list-style style:name="L1"> + <text:list-level-style-bullet text:level="1" text:bullet-char="-"> + <style:list-level-properties text:min-label-width="0.6cm"/> + <style:text-properties fo:font-family="OpenSymbol" style:font-style-name="Regular" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/> + </text:list-level-style-bullet> + </text:list-style> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Default" style:page-layout-name="PM1"> + </style:master-page> + </office:master-styles> + <office:body> + <office:presentation> + <draw:page draw:name="page1" draw:master-page-name="Default"> + <draw:frame draw:style-name="gr1" draw:text-style-name="P8" draw:layer="layout" svg:width="9.525cm" svg:height="0.962cm" svg:x="3.175cm" svg:y="2.54cm"> + <draw:text-box> + <text:list text:style-name="L1"> + <text:list-item> + <text:p>hello</text:p> + </text:list-item> + </text:list> + </draw:text-box> + </draw:frame> + </draw:page> + </office:presentation> + </office:body> +</office:document> diff --git a/filter/qa/unit/svg.cxx b/filter/qa/unit/svg.cxx index bb7600d71626..8f03e7120d75 100644 --- a/filter/qa/unit/svg.cxx +++ b/filter/qa/unit/svg.cxx @@ -179,6 +179,33 @@ CPPUNIT_TEST_FIXTURE(SvgFilterTest, testShapeNographic) xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList()); } +CPPUNIT_TEST_FIXTURE(SvgFilterTest, testCustomBullet) +{ + // Given a presentation with a custom bullet: + load(u"custom-bullet.fodp"); + + // When exporting that to SVG: + uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW); + SvMemoryStream aStream; + uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("impress_svg_Export"); + aMediaDescriptor["OutputStream"] <<= xOut; + xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList()); + + // Then make sure the bullet glyph is not lost: + aStream.Seek(STREAM_SEEK_TO_BEGIN); + xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // - XPath '//svg:g[@class='BulletChars']//svg:path' number of nodes is incorrect + // i.e. the custom bullet used '<use transform="scale(285,285)" + // xlink:href="#bullet-char-template-45"/>', but nobody produced a bullet-char-template-45, + // instead we need the path of the glyph inline. + CPPUNIT_ASSERT(!getXPath(pXmlDoc, "//svg:g[@class='BulletChars']//svg:path", "d").isEmpty()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx index 2c8130667c6b..fc8de3b18f68 100644 --- a/filter/source/svg/svgexport.cxx +++ b/filter/source/svg/svgexport.cxx @@ -1531,6 +1531,7 @@ void SVGFilter::implEmbedBulletGlyph( sal_Unicode cBullet, const OUString & sPat mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "d", sPathData ); SvXMLElementExport aPathElem( *mpSVGExport, XML_NAMESPACE_NONE, "path", true, true ); + mpSVGExport->SetEmbeddedBulletGlyph(cBullet); } void SVGFilter::implExportBackgroundBitmaps() @@ -2865,4 +2866,15 @@ void SVGExport::writeMtf( const GDIMetaFile& rMtf ) } } +void SVGExport::SetEmbeddedBulletGlyph(sal_Unicode cBullet) +{ + maEmbeddedBulletGlyphs.insert(cBullet); +} + +bool SVGExport::IsEmbeddedBulletGlyph(sal_Unicode cBullet) const +{ + auto it = maEmbeddedBulletGlyphs.find(cBullet); + return it != maEmbeddedBulletGlyphs.end(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx index 7bdaa9d60f09..aab158971e0b 100644 --- a/filter/source/svg/svgfilter.hxx +++ b/filter/source/svg/svgfilter.hxx @@ -66,6 +66,7 @@ class SVGExport : public SvXMLExport bool mbIsUseOpacity; bool mbIsUseNativeTextDecoration; bool mbIsUsePositionedCharacters; + std::set<sal_Unicode> maEmbeddedBulletGlyphs; public: @@ -84,6 +85,9 @@ public: void writeMtf( const GDIMetaFile& rMtf ); + void SetEmbeddedBulletGlyph(sal_Unicode cBullet); + bool IsEmbeddedBulletGlyph(sal_Unicode cBullet) const; + protected: virtual void ExportStyles_( bool /* bUsed */ ) override {} diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx index 57ccc67bf6ef..866594439abc 100644 --- a/filter/source/svg/svgwriter.cxx +++ b/filter/source/svg/svgwriter.cxx @@ -1428,11 +1428,12 @@ void SVGTextWriter::implWriteBulletChars() SvXMLElementExport aPositioningElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true ); - // <use transform="scale(font-size)" xlink:ref="/" > + if (mrExport.IsEmbeddedBulletGlyph(rInfo.cBulletChar)) { + // <use transform="scale(font-size)" xlink:ref="/" > // Add size attribute through a scaling - sScaling = "scale(" + OUString::number( rInfo.nFontSize ) + - "," + OUString::number( rInfo.nFontSize )+ ")"; + sScaling = "scale(" + OUString::number( rInfo.aFont.GetFontHeight() ) + + "," + OUString::number( rInfo.aFont.GetFontHeight() )+ ")"; mrExport.AddAttribute( XML_NAMESPACE_NONE, "transform", sScaling ); // Add ref attribute @@ -1442,6 +1443,21 @@ void SVGTextWriter::implWriteBulletChars() SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", true, true ); } + else + { + // <path d="..."> + tools::PolyPolygon aPolyPolygon; + OUString aStr(rInfo.cBulletChar); + mpVDev->Push(PushFlags::FONT); + mpVDev->SetFont(rInfo.aFont); + if (mpVDev->GetTextOutline(aPolyPolygon, aStr)) + { + OUString aPathString(SVGActionWriter::GetPathString(aPolyPolygon, false)); + mrExport.AddAttribute(XML_NAMESPACE_NONE, "d", aPathString); + SvXMLElementExport aPath(mrExport, XML_NAMESPACE_NONE, "path", true, true); + } + mpVDev->Pop(); + } } // close aPositioningElem } @@ -1696,7 +1712,7 @@ void SVGTextWriter::implWriteTextPortion( const Point& rPos, { sId += ".bp"; BulletListItemInfo& aBulletListItemInfo = maBulletListItemMap[ sId ]; - aBulletListItemInfo.nFontSize = rFont.GetFontHeight(); + aBulletListItemInfo.aFont = rFont; aBulletListItemInfo.aColor = aTextColor; aBulletListItemInfo.aPos = maTextPos; aBulletListItemInfo.cBulletChar = mcBulletChar; diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx index 993d1162fcf3..a052fba16e87 100644 --- a/filter/source/svg/svgwriter.hxx +++ b/filter/source/svg/svgwriter.hxx @@ -189,7 +189,7 @@ class GDIMetaFile; struct BulletListItemInfo { - tools::Long nFontSize; + vcl::Font aFont; Color aColor; Point aPos; sal_Unicode cBulletChar; |