summaryrefslogtreecommitdiff
path: root/writerperfect/source
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2017-11-28 09:06:07 +0100
committerMiklos Vajna <vmiklos@collabora.co.uk>2017-11-29 09:17:04 +0100
commit793bbac379c5800dc09ff76f093d45047e662ff0 (patch)
treebb8c87fd245cff92dd332a0959e6d3ec21d5b32e /writerperfect/source
parent3ece8264b4c0b41f480e77980b987db4540e49e7 (diff)
EPUB export: implement font embedding support
Also avoid librevenge::RVNGBinaryData::appendBase64Data() for performance reasons. Times with and without the XMLBase64ImportContext rework for sw/qa/extras/odfexport/data/embedded-font-props.odt: - before: 1m32.254s - after: 0m7.045s (Need to insvestigate macOS font embedding situation in general, later.) Change-Id: I5aa56bfbfa8dc64f19c021202a1b87618b4b2775 Reviewed-on: https://gerrit.libreoffice.org/45385 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Diffstat (limited to 'writerperfect/source')
-rw-r--r--writerperfect/source/writer/exp/XMLBase64ImportContext.cxx25
-rw-r--r--writerperfect/source/writer/exp/XMLBase64ImportContext.hxx4
-rw-r--r--writerperfect/source/writer/exp/xmlfmt.cxx169
-rw-r--r--writerperfect/source/writer/exp/xmlfmt.hxx9
-rw-r--r--writerperfect/source/writer/exp/xmlimp.cxx2
5 files changed, 207 insertions, 2 deletions
diff --git a/writerperfect/source/writer/exp/XMLBase64ImportContext.cxx b/writerperfect/source/writer/exp/XMLBase64ImportContext.cxx
index c073d8fc19bd..137bf01aff01 100644
--- a/writerperfect/source/writer/exp/XMLBase64ImportContext.cxx
+++ b/writerperfect/source/writer/exp/XMLBase64ImportContext.cxx
@@ -9,6 +9,8 @@
#include "XMLBase64ImportContext.hxx"
+#include <comphelper/base64.hxx>
+
using namespace com::sun::star;
namespace writerperfect
@@ -27,12 +29,31 @@ void XMLBase64ImportContext::startElement(const OUString &/*rName*/, const css::
void XMLBase64ImportContext::endElement(const OUString &/*rName*/)
{
+ m_aBinaryData.append(static_cast<const unsigned char *>(m_aStream.GetBuffer()), m_aStream.GetSize());
}
void XMLBase64ImportContext::characters(const OUString &rChars)
{
- OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
- m_aBinaryData.appendBase64Data(librevenge::RVNGString(sCharU8.getStr()));
+ OUString aTrimmedChars(rChars.trim());
+
+ if (!aTrimmedChars.isEmpty())
+ {
+ OUString aChars;
+ if (!m_aBase64CharsLeft.isEmpty())
+ {
+ aChars = m_aBase64CharsLeft;
+ aChars += aTrimmedChars;
+ m_aBase64CharsLeft.clear();
+ }
+ else
+ aChars = aTrimmedChars;
+
+ uno::Sequence<sal_Int8> aBuffer((aChars.getLength() / 4) * 3);
+ const sal_Int32 nCharsDecoded = comphelper::Base64::decodeSomeChars(aBuffer, aChars);
+ m_aStream.WriteBytes(aBuffer.getArray(), aBuffer.getLength());
+ if (nCharsDecoded != aChars.getLength())
+ m_aBase64CharsLeft = aChars.copy(nCharsDecoded);
+ }
}
const librevenge::RVNGBinaryData &XMLBase64ImportContext::getBinaryData() const
diff --git a/writerperfect/source/writer/exp/XMLBase64ImportContext.hxx b/writerperfect/source/writer/exp/XMLBase64ImportContext.hxx
index f60122b61382..6ad850a825c1 100644
--- a/writerperfect/source/writer/exp/XMLBase64ImportContext.hxx
+++ b/writerperfect/source/writer/exp/XMLBase64ImportContext.hxx
@@ -12,6 +12,8 @@
#include <librevenge/RVNGBinaryData.h>
+#include <tools/stream.hxx>
+
#include "xmlictxt.hxx"
namespace writerperfect
@@ -33,6 +35,8 @@ public:
private:
librevenge::RVNGBinaryData m_aBinaryData;
+ SvMemoryStream m_aStream;
+ OUString m_aBase64CharsLeft;
};
} // namespace exp
diff --git a/writerperfect/source/writer/exp/xmlfmt.cxx b/writerperfect/source/writer/exp/xmlfmt.cxx
index 02f96f691e9b..abd6bb9a6a72 100644
--- a/writerperfect/source/writer/exp/xmlfmt.cxx
+++ b/writerperfect/source/writer/exp/xmlfmt.cxx
@@ -9,6 +9,7 @@
#include "xmlfmt.hxx"
+#include "XMLBase64ImportContext.hxx"
#include "txtstyli.hxx"
#include "xmlimp.hxx"
@@ -73,6 +74,174 @@ std::map<OUString, librevenge::RVNGPropertyList> &XMLStylesContext::GetCurrentGr
return m_rGraphicStyles;
}
+/// Handler for <style:font-face>.
+class XMLFontFaceContext : public XMLImportContext
+{
+public:
+ XMLFontFaceContext(XMLImport &rImport);
+ void SAL_CALL startElement(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) override;
+
+ rtl::Reference<XMLImportContext> CreateChildContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) override;
+
+ OUString maName;
+};
+
+/// Handler for <svg:font-face-src>.
+class XMLFontFaceSrcContext : public XMLImportContext
+{
+public:
+ XMLFontFaceSrcContext(XMLImport &rImport, XMLFontFaceContext &rFontFace);
+
+ rtl::Reference<XMLImportContext> CreateChildContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) override;
+
+private:
+ XMLFontFaceContext &mrFontFace;
+};
+
+/// Handler for <svg:font-face-uri>.
+class XMLFontFaceUriContext : public XMLImportContext
+{
+public:
+ XMLFontFaceUriContext(XMLImport &rImport, XMLFontFaceContext &rFontFace);
+ void SAL_CALL startElement(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) override;
+ void SAL_CALL endElement(const OUString &rName) override;
+
+ rtl::Reference<XMLImportContext> CreateChildContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) override;
+
+ librevenge::RVNGPropertyList maPropertyList;
+
+private:
+ rtl::Reference<XMLBase64ImportContext> mxBinaryData;
+};
+
+/// Handler for <svg:font-face-format>.
+class XMLFontFaceFormatContext : public XMLImportContext
+{
+public:
+ XMLFontFaceFormatContext(XMLImport &rImport, XMLFontFaceUriContext &rFontUri);
+ void SAL_CALL startElement(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) override;
+
+private:
+ XMLFontFaceUriContext &mrFontFaceUri;
+};
+
+XMLFontFaceFormatContext::XMLFontFaceFormatContext(XMLImport &rImport, XMLFontFaceUriContext &rFontFaceUri)
+ : XMLImportContext(rImport)
+ , mrFontFaceUri(rFontFaceUri)
+{
+}
+
+void XMLFontFaceFormatContext::startElement(const OUString &/*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs)
+{
+ for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
+ {
+ const OUString &rAttributeName = xAttribs->getNameByIndex(i);
+ const OUString &rAttributeValue = xAttribs->getValueByIndex(i);
+ if (rAttributeName == "svg:string")
+ {
+ OString aAttributeValueU8 = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8);
+ mrFontFaceUri.maPropertyList.insert("librevenge:mime-type", aAttributeValueU8.getStr());
+ }
+ }
+}
+
+XMLFontFaceUriContext::XMLFontFaceUriContext(XMLImport &rImport, XMLFontFaceContext &rFontFace)
+ : XMLImportContext(rImport)
+{
+ OString aNameU8 = OUStringToOString(rFontFace.maName, RTL_TEXTENCODING_UTF8);
+ maPropertyList.insert("librevenge:name", aNameU8.getStr());
+}
+
+void XMLFontFaceUriContext::startElement(const OUString &/*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs)
+{
+ for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
+ {
+ const OUString &rAttributeName = xAttribs->getNameByIndex(i);
+ const OUString &rAttributeValue = xAttribs->getValueByIndex(i);
+ if (rAttributeName == "loext:font-style")
+ {
+ OString aAttributeValueU8 = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8);
+ maPropertyList.insert("librevenge:font-style", aAttributeValueU8.getStr());
+ }
+ else if (rAttributeName == "loext:font-weight")
+ {
+ OString aAttributeValueU8 = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8);
+ maPropertyList.insert("librevenge:font-weight", aAttributeValueU8.getStr());
+ }
+ }
+}
+
+void XMLFontFaceUriContext::endElement(const OUString &/*rName*/)
+{
+ if (mxBinaryData.is())
+ maPropertyList.insert("office:binary-data", mxBinaryData->getBinaryData());
+ mrImport.GetGenerator().defineEmbeddedFont(maPropertyList);
+}
+
+rtl::Reference<XMLImportContext> XMLFontFaceUriContext::CreateChildContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/)
+{
+ if (rName == "office:binary-data")
+ {
+ mxBinaryData = new XMLBase64ImportContext(mrImport);
+ return mxBinaryData.get();
+ }
+ if (rName == "svg:font-face-format")
+ return new XMLFontFaceFormatContext(mrImport, *this);
+
+ SAL_WARN("writerperfect", "XMLFontFaceUriContext::CreateChildContext: unhandled " << rName);
+ return nullptr;
+}
+
+XMLFontFaceSrcContext::XMLFontFaceSrcContext(XMLImport &rImport, XMLFontFaceContext &rFontFace)
+ : XMLImportContext(rImport)
+ , mrFontFace(rFontFace)
+{
+}
+
+rtl::Reference<XMLImportContext> XMLFontFaceSrcContext::CreateChildContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/)
+{
+ if (rName == "svg:font-face-uri")
+ return new XMLFontFaceUriContext(mrImport, mrFontFace);
+ SAL_WARN("writerperfect", "XMLFontFaceSrcContext::CreateChildContext: unhandled " << rName);
+ return nullptr;
+}
+
+XMLFontFaceContext::XMLFontFaceContext(XMLImport &rImport)
+ : XMLImportContext(rImport)
+{
+}
+
+void XMLFontFaceContext::startElement(const OUString &/*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs)
+{
+ for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
+ {
+ const OUString &rAttributeName = xAttribs->getNameByIndex(i);
+ const OUString &rAttributeValue = xAttribs->getValueByIndex(i);
+ if (rAttributeName == "style:name")
+ maName = rAttributeValue;
+ }
+}
+
+rtl::Reference<XMLImportContext> XMLFontFaceContext::CreateChildContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/)
+{
+ if (rName == "svg:font-face-src")
+ return new XMLFontFaceSrcContext(mrImport, *this);
+ SAL_WARN("writerperfect", "XMLFontFaceContext::CreateChildContext: unhandled " << rName);
+ return nullptr;
+}
+
+XMLFontFaceDeclsContext::XMLFontFaceDeclsContext(XMLImport &rImport)
+ : XMLImportContext(rImport)
+{
+}
+
+rtl::Reference<XMLImportContext> XMLFontFaceDeclsContext::CreateChildContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/)
+{
+ if (rName == "style:font-face")
+ return new XMLFontFaceContext(mrImport);
+ return nullptr;
+}
+
} // namespace exp
} // namespace writerperfect
diff --git a/writerperfect/source/writer/exp/xmlfmt.hxx b/writerperfect/source/writer/exp/xmlfmt.hxx
index f4d82273b4f1..3f609e98b000 100644
--- a/writerperfect/source/writer/exp/xmlfmt.hxx
+++ b/writerperfect/source/writer/exp/xmlfmt.hxx
@@ -46,6 +46,15 @@ private:
std::map<OUString, librevenge::RVNGPropertyList> &m_rGraphicStyles;
};
+/// Handler for <office:font-face-decls>.
+class XMLFontFaceDeclsContext : public XMLImportContext
+{
+public:
+ XMLFontFaceDeclsContext(XMLImport &rImport);
+
+ rtl::Reference<XMLImportContext> CreateChildContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) override;
+};
+
} // namespace exp
} // namespace writerperfect
diff --git a/writerperfect/source/writer/exp/xmlimp.cxx b/writerperfect/source/writer/exp/xmlimp.cxx
index b301cb3deb0f..30a7ee03d404 100644
--- a/writerperfect/source/writer/exp/xmlimp.cxx
+++ b/writerperfect/source/writer/exp/xmlimp.cxx
@@ -66,6 +66,8 @@ rtl::Reference<XMLImportContext> XMLOfficeDocContext::CreateChildContext(const O
return new XMLStylesContext(mrImport, /*bAutomatic=*/true);
else if (rName == "office:styles")
return new XMLStylesContext(mrImport, /*bAutomatic=*/false);
+ else if (rName == "office:font-face-decls")
+ return new XMLFontFaceDeclsContext(mrImport);
return nullptr;
}