diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-01-17 11:47:14 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-01-17 13:23:57 +0100 |
commit | bbc4360b5beb012adf1e2652328d3e18d66224aa (patch) | |
tree | dbc5d12e8a45cb839da9ffd7b68305590d8e518a /filter | |
parent | 586a0f149f332c0b0e53c0bb30568d4bd411b0e3 (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.
Change-Id: I3de8fab8dc6c78e273629d13566d1f9f289eb752
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128495
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
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 e1b54fb2a294..3e3508fd52ca 100644 --- a/filter/qa/unit/svg.cxx +++ b/filter/qa/unit/svg.cxx @@ -182,6 +182,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 170b2cf1437b..ef0c1ea37a80 100644 --- a/filter/source/svg/svgexport.cxx +++ b/filter/source/svg/svgexport.cxx @@ -1524,6 +1524,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() @@ -2858,4 +2859,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 1a8796bd9046..eb889e81662e 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 a9dcfccbb627..e066806cea9a 100644 --- a/filter/source/svg/svgwriter.cxx +++ b/filter/source/svg/svgwriter.cxx @@ -1416,11 +1416,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 @@ -1430,6 +1431,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(vcl::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 } @@ -1684,7 +1700,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 9fe8a698c85e..fdfcd24d32b2 100644 --- a/filter/source/svg/svgwriter.hxx +++ b/filter/source/svg/svgwriter.hxx @@ -188,7 +188,7 @@ class GDIMetaFile; struct BulletListItemInfo { - tools::Long nFontSize; + vcl::Font aFont; Color aColor; Point aPos; sal_Unicode cBulletChar; |