diff options
author | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-11-28 09:06:07 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-11-29 09:17:04 +0100 |
commit | 793bbac379c5800dc09ff76f093d45047e662ff0 (patch) | |
tree | bb8c87fd245cff92dd332a0959e6d3ec21d5b32e /writerperfect/source | |
parent | 3ece8264b4c0b41f480e77980b987db4540e49e7 (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.cxx | 25 | ||||
-rw-r--r-- | writerperfect/source/writer/exp/XMLBase64ImportContext.hxx | 4 | ||||
-rw-r--r-- | writerperfect/source/writer/exp/xmlfmt.cxx | 169 | ||||
-rw-r--r-- | writerperfect/source/writer/exp/xmlfmt.hxx | 9 | ||||
-rw-r--r-- | writerperfect/source/writer/exp/xmlimp.cxx | 2 |
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; } |