summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-01-17 11:47:14 +0100
committerMike Kaganski <mike.kaganski@collabora.com>2022-01-18 08:20:36 +0100
commit38da870731123d8ad97b62f95c61ec8c1257d9a9 (patch)
treeed73ce06e2e9c15d237d91d0a6ee89a694ce88dd
parentsvx-lok: incomplete invalidation when resizing/deleting... (diff)
downloadcore-38da870731123d8ad97b62f95c61ec8c1257d9a9.tar.gz
core-38da870731123d8ad97b62f95c61ec8c1257d9a9.zip
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>
-rw-r--r--filter/qa/unit/data/custom-bullet.fodp36
-rw-r--r--filter/qa/unit/svg.cxx27
-rw-r--r--filter/source/svg/svgexport.cxx12
-rw-r--r--filter/source/svg/svgfilter.hxx4
-rw-r--r--filter/source/svg/svgwriter.cxx24
-rw-r--r--filter/source/svg/svgwriter.hxx2
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;