diff options
author | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-09-08 15:55:03 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-09-08 17:56:22 +0200 |
commit | 687fdc5750ac756f157c663197b998eb471612ef (patch) | |
tree | 23b0ecc6c37a540400ec28f9bcb71f9c1e3e4574 /writerperfect | |
parent | 8d1c4032ed284e656300801b62c982e212315a07 (diff) |
EPUB export: inherit text properties in spans from paragraph
This is similar to nested spans, but here the outer element is a
paragraph.
Change-Id: Ibcdfe5aac54a44797067b06d319d19d2d47d5dd1
Reviewed-on: https://gerrit.libreoffice.org/42104
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Tested-by: Jenkins <ci@libreoffice.org>
Diffstat (limited to 'writerperfect')
-rw-r--r-- | writerperfect/qa/unit/EPUBExportTest.cxx | 21 | ||||
-rw-r--r-- | writerperfect/qa/unit/data/writer/epubexport/para-char-props.fodt | 16 | ||||
-rw-r--r-- | writerperfect/source/writer/exp/txtparai.cxx | 79 | ||||
-rw-r--r-- | writerperfect/source/writer/exp/txtparai.hxx | 4 |
4 files changed, 86 insertions, 34 deletions
diff --git a/writerperfect/qa/unit/EPUBExportTest.cxx b/writerperfect/qa/unit/EPUBExportTest.cxx index 10fd5eb5a94a..06278d19eb81 100644 --- a/writerperfect/qa/unit/EPUBExportTest.cxx +++ b/writerperfect/qa/unit/EPUBExportTest.cxx @@ -64,6 +64,7 @@ public: void testNestedSpan(); void testLineBreak(); void testEscape(); + void testParaCharProps(); CPPUNIT_TEST_SUITE(EPUBExportTest); CPPUNIT_TEST(testOutlineLevel); @@ -79,6 +80,7 @@ public: CPPUNIT_TEST(testNestedSpan); CPPUNIT_TEST(testLineBreak); CPPUNIT_TEST(testEscape); + CPPUNIT_TEST(testParaCharProps); CPPUNIT_TEST_SUITE_END(); }; @@ -327,9 +329,9 @@ void EPUBExportTest::testLineBreak() mpXmlDoc = parseExport("OEBPS/sections/section0001.xhtml"); // This was 0, line break was not handled. - assertXPath(mpXmlDoc, "//xhtml:p[1]/xhtml:br", 1); + assertXPath(mpXmlDoc, "//xhtml:p[1]/xhtml:span/xhtml:br", 1); // This was 0, line break inside span was not handled. - assertXPath(mpXmlDoc, "//xhtml:p[2]/xhtml:br", 1); + assertXPath(mpXmlDoc, "//xhtml:p[2]/xhtml:span/xhtml:br", 1); } void EPUBExportTest::testEscape() @@ -345,6 +347,21 @@ void EPUBExportTest::testEscape() assertXPathContent(mpXmlDoc, "//xhtml:p[1]/xhtml:span[3]", "\t"); } +void EPUBExportTest::testParaCharProps() +{ + createDoc("para-char-props.fodt", {}); + + mpXmlDoc = parseExport("OEBPS/sections/section0001.xhtml"); + // Check formatting of the middle span. + OString aMiddle = getXPath(mpXmlDoc, "//xhtml:p/xhtml:span[2]", "class").toUtf8(); + std::map< OString, std::vector<OString> > aCssDoc; + parseCssExport("OEBPS/styles/stylesheet.css", aCssDoc); + assertCss(aCssDoc, aMiddle, " font-style: italic;"); + // Direct para formatting was lost, only direct char formatting was + // written, so this failed. + assertCss(aCssDoc, aMiddle, " font-weight: bold;"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(EPUBExportTest); } diff --git a/writerperfect/qa/unit/data/writer/epubexport/para-char-props.fodt b/writerperfect/qa/unit/data/writer/epubexport/para-char-props.fodt new file mode 100644 index 000000000000..67fe02db2bc5 --- /dev/null +++ b/writerperfect/qa/unit/data/writer/epubexport/para-char-props.fodt @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph"> + <style:text-properties fo:font-weight="bold" /> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties fo:font-style="italic"/> + </style:style> + </office:automatic-styles> + <office:body> + <office:text> + <text:p text:style-name="P1">a<text:span text:style-name="T1">b</text:span>c</text:p> + </office:text> + </office:body> +</office:document> diff --git a/writerperfect/source/writer/exp/txtparai.cxx b/writerperfect/source/writer/exp/txtparai.cxx index e660a34b1e30..8e19475b65fe 100644 --- a/writerperfect/source/writer/exp/txtparai.cxx +++ b/writerperfect/source/writer/exp/txtparai.cxx @@ -74,7 +74,7 @@ namespace exp class XMLSpanContext : public XMLImportContext { public: - XMLSpanContext(XMLImport &rImport, const librevenge::RVNGPropertyList *pPropertyList); + XMLSpanContext(XMLImport &rImport, const librevenge::RVNGPropertyList &rPropertyList); XMLImportContext *CreateChildContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) override; @@ -85,14 +85,11 @@ private: librevenge::RVNGPropertyList m_aPropertyList; }; -XMLSpanContext::XMLSpanContext(XMLImport &rImport, const librevenge::RVNGPropertyList *pPropertyList) +XMLSpanContext::XMLSpanContext(XMLImport &rImport, const librevenge::RVNGPropertyList &rPropertyList) : XMLImportContext(rImport) { - if (!pPropertyList) - return; - - // Inherit properties from parent span. - librevenge::RVNGPropertyList::Iter itProp(*pPropertyList); + // Inherit properties from parent. + librevenge::RVNGPropertyList::Iter itProp(rPropertyList); for (itProp.rewind(); itProp.next();) m_aPropertyList.insert(itProp.key(), itProp()->clone()); } @@ -101,9 +98,7 @@ XMLImportContext *XMLSpanContext::CreateChildContext(const OUString &rName, cons { if (rName == "draw:frame") return new XMLTextFrameContext(mrImport); - if (rName == "text:span") - return new XMLSpanContext(mrImport, &m_aPropertyList); - return writerperfect::exp::CreateChildContext(mrImport, rName); + return CreateParagraphOrSpanChildContext(mrImport, rName, m_aPropertyList); } void XMLSpanContext::startElement(const OUString &/*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) @@ -133,63 +128,84 @@ void XMLSpanContext::characters(const OUString &rChars) mrImport.GetGenerator().closeSpan(); } +/// Base class for contexts that represent a single character only. +class XMLCharContext : public XMLImportContext +{ +public: + XMLCharContext(XMLImport &rImport, const librevenge::RVNGPropertyList &rPropertyList); + +protected: + librevenge::RVNGPropertyList m_aPropertyList; +}; + +XMLCharContext::XMLCharContext(XMLImport &rImport, const librevenge::RVNGPropertyList &rPropertyList) + : XMLImportContext(rImport) +{ + // Inherit properties from parent. + librevenge::RVNGPropertyList::Iter itProp(rPropertyList); + for (itProp.rewind(); itProp.next();) + m_aPropertyList.insert(itProp.key(), itProp()->clone()); +} + /// Handler for <text:line-break>. -class XMLLineBreakContext : public XMLImportContext +class XMLLineBreakContext : public XMLCharContext { public: - XMLLineBreakContext(XMLImport &rImport); + XMLLineBreakContext(XMLImport &rImport, const librevenge::RVNGPropertyList &rPropertyList); void SAL_CALL startElement(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) override; }; -XMLLineBreakContext::XMLLineBreakContext(XMLImport &rImport) - : XMLImportContext(rImport) +XMLLineBreakContext::XMLLineBreakContext(XMLImport &rImport, const librevenge::RVNGPropertyList &rPropertyList) + : XMLCharContext(rImport, rPropertyList) { } void XMLLineBreakContext::startElement(const OUString &/*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/) { + mrImport.GetGenerator().openSpan(m_aPropertyList); mrImport.GetGenerator().insertLineBreak(); + mrImport.GetGenerator().closeSpan(); } /// Handler for <text:s>. -class XMLSpaceContext : public XMLImportContext +class XMLSpaceContext : public XMLCharContext { public: - XMLSpaceContext(XMLImport &rImport); + XMLSpaceContext(XMLImport &rImport, const librevenge::RVNGPropertyList &rPropertyList); void SAL_CALL startElement(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) override; }; -XMLSpaceContext::XMLSpaceContext(XMLImport &rImport) - : XMLImportContext(rImport) +XMLSpaceContext::XMLSpaceContext(XMLImport &rImport, const librevenge::RVNGPropertyList &rPropertyList) + : XMLCharContext(rImport, rPropertyList) { } void XMLSpaceContext::startElement(const OUString &/*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/) { - mrImport.GetGenerator().openSpan(librevenge::RVNGPropertyList()); + mrImport.GetGenerator().openSpan(m_aPropertyList); mrImport.GetGenerator().insertSpace(); mrImport.GetGenerator().closeSpan(); } /// Handler for <text:tab>. -class XMLTabContext : public XMLImportContext +class XMLTabContext : public XMLCharContext { public: - XMLTabContext(XMLImport &rImport); + XMLTabContext(XMLImport &rImport, const librevenge::RVNGPropertyList &rPropertyList); void SAL_CALL startElement(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) override; }; -XMLTabContext::XMLTabContext(XMLImport &rImport) - : XMLImportContext(rImport) +XMLTabContext::XMLTabContext(XMLImport &rImport, const librevenge::RVNGPropertyList &rPropertyList) + : XMLCharContext(rImport, rPropertyList) { } void XMLTabContext::startElement(const OUString &/*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/) { - mrImport.GetGenerator().openSpan(librevenge::RVNGPropertyList()); + mrImport.GetGenerator().openSpan(m_aPropertyList); mrImport.GetGenerator().insertTab(); mrImport.GetGenerator().closeSpan(); } @@ -245,11 +261,9 @@ XMLParaContext::XMLParaContext(XMLImport &rImport) XMLImportContext *XMLParaContext::CreateChildContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &/*xAttribs*/) { - if (rName == "text:span") - return new XMLSpanContext(mrImport, nullptr); if (rName == "text:a") return new XMLHyperlinkContext(mrImport); - return writerperfect::exp::CreateChildContext(mrImport, rName); + return CreateParagraphOrSpanChildContext(mrImport, rName, m_aTextPropertyList); } void XMLParaContext::startElement(const OUString &/*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs) @@ -263,6 +277,7 @@ void XMLParaContext::startElement(const OUString &/*rName*/, const css::uno::Ref { m_aStyleName = rAttributeValue; FillStyles(m_aStyleName, mrImport.GetAutomaticParagraphStyles(), mrImport.GetParagraphStyles(), aPropertyList); + FillStyles(m_aStyleName, mrImport.GetAutomaticTextStyles(), mrImport.GetTextStyles(), m_aTextPropertyList); } else { @@ -293,14 +308,16 @@ void XMLParaContext::characters(const OUString &rChars) mrImport.GetGenerator().closeSpan(); } -XMLImportContext *CreateChildContext(XMLImport &rImport, const OUString &rName) +XMLImportContext *CreateParagraphOrSpanChildContext(XMLImport &rImport, const OUString &rName, const librevenge::RVNGPropertyList &rTextPropertyList) { + if (rName == "text:span") + return new XMLSpanContext(rImport, rTextPropertyList); if (rName == "text:line-break") - return new XMLLineBreakContext(rImport); + return new XMLLineBreakContext(rImport, rTextPropertyList); if (rName == "text:s") - return new XMLSpaceContext(rImport); + return new XMLSpaceContext(rImport, rTextPropertyList); if (rName == "text:tab") - return new XMLTabContext(rImport); + return new XMLTabContext(rImport, rTextPropertyList); return nullptr; } diff --git a/writerperfect/source/writer/exp/txtparai.hxx b/writerperfect/source/writer/exp/txtparai.hxx index 52543ffeadde..a427d2602516 100644 --- a/writerperfect/source/writer/exp/txtparai.hxx +++ b/writerperfect/source/writer/exp/txtparai.hxx @@ -31,10 +31,12 @@ public: private: OUString m_aStyleName; + /// List of properties spans should inherit from this paragraph. + librevenge::RVNGPropertyList m_aTextPropertyList; }; /// Shared child context factory for paragraph and span contexts. -XMLImportContext *CreateChildContext(XMLImport &rImport, const OUString &rName); +XMLImportContext *CreateParagraphOrSpanChildContext(XMLImport &rImport, const OUString &rName, const librevenge::RVNGPropertyList &rTextPropertyList); } // namespace exp } // namespace writerperfect |