EPUB export: support char props on text outside a span

The librevenge model is simpler: text is always in a span, and paragraph
(automatic) styles don't contain char props, either. So handle this
complexity on our side.

Change-Id: I017222539d8981d2bbbc632258662444bf3a79c8
Reviewed-on: https://gerrit.libreoffice.org/41705
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Tested-by: Jenkins <ci@libreoffice.org>
This commit is contained in:
Miklos Vajna
2017-08-29 17:56:28 +02:00
parent 0be2ac10cb
commit dfdc113bbd
8 changed files with 93 additions and 21 deletions

View File

@@ -52,6 +52,7 @@ public:
void testEPUB2();
void testPageBreakSplit();
void testSpanAutostyle();
void testParaAutostyleCharProps();
CPPUNIT_TEST_SUITE(EPUBExportTest);
CPPUNIT_TEST(testOutlineLevel);
@@ -59,6 +60,7 @@ public:
CPPUNIT_TEST(testEPUB2);
CPPUNIT_TEST(testPageBreakSplit);
CPPUNIT_TEST(testSpanAutostyle);
CPPUNIT_TEST(testParaAutostyleCharProps);
CPPUNIT_TEST_SUITE_END();
};
@@ -190,6 +192,16 @@ void EPUBExportTest::testSpanAutostyle()
assertXPath(mpXmlDoc, "//xhtml:p/xhtml:span[3]", "class", "span2");
}
void EPUBExportTest::testParaAutostyleCharProps()
{
createDoc("para-autostyle-char-props.fodt", {});
mpXmlDoc = parseExport("OEBPS/sections/section0001.xhtml");
// This failed, para-level char props were not exported.
assertXPath(mpXmlDoc, "//xhtml:p[1]/xhtml:span", "class", "span0");
assertXPath(mpXmlDoc, "//xhtml:p[2]/xhtml:span", "class", "span1");
}
CPPUNIT_TEST_SUITE_REGISTRATION(EPUBExportTest);
}

View File

@@ -0,0 +1,21 @@
<?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" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
<office:font-face-decls>
<style:font-face style:name="Liberation Serif" svg:font-family="&apos;Liberation Serif&apos;" style:font-family-generic="roman" style:font-pitch="variable"/>
<style:font-face style:name="Liberation Sans" svg:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="swiss" style:font-pitch="variable"/>
</office:font-face-decls>
<office:automatic-styles>
<style:style style:name="P1" style:family="paragraph">
<style:text-properties style:font-name="Liberation Serif"/>
</style:style>
<style:style style:name="P2" style:family="paragraph">
<style:text-properties style:font-name="Liberation Sans"/>
</style:style>
</office:automatic-styles>
<office:body>
<office:text>
<text:p text:style-name="P1">This is serif.</text:p>
<text:p text:style-name="P2">This is sans.</text:p>
</office:text>
</office:body>
</office:document>

View File

@@ -53,9 +53,9 @@ void XMLSpanContext::startElement(const OUString &/*rName*/, const css::uno::Ref
const OUString &rAttributeValue = xAttribs->getValueByIndex(i);
if (rAttributeName == "text:style-name")
{
// Reference to an automatic style, try to look it up.
auto itStyle = mrImport.GetAutomaticStyles().find(rAttributeValue);
if (itStyle == mrImport.GetAutomaticStyles().end())
// Reference to an automatic text style, try to look it up.
auto itStyle = mrImport.GetAutomaticTextStyles().find(rAttributeValue);
if (itStyle == mrImport.GetAutomaticTextStyles().end())
continue;
// Apply properties directly, librevenge has no notion of automatic styles.
@@ -152,15 +152,17 @@ void XMLParaContext::startElement(const OUString &/*rName*/, const css::uno::Ref
const OUString &rAttributeValue = xAttribs->getValueByIndex(i);
if (rAttributeName == "text:style-name")
{
m_aStyleName = rAttributeValue;
// Reference to an automatic style, try to look it up.
auto itStyle = mrImport.GetAutomaticStyles().find(rAttributeValue);
if (itStyle == mrImport.GetAutomaticStyles().end())
auto itStyle = mrImport.GetAutomaticParagraphStyles().find(m_aStyleName);
if (itStyle == mrImport.GetAutomaticParagraphStyles().end())
continue;
// Apply properties directly, librevenge has no notion of automatic styles.
// Found an automatic paragraph style.
librevenge::RVNGPropertyList::Iter itProp(itStyle->second);
for (itProp.rewind(); itProp.next();)
aPropertyList.insert(itProp.key(), itProp());
aPropertyList.insert(itProp.key(), itProp()->clone());
}
else
{
@@ -180,8 +182,25 @@ void XMLParaContext::endElement(const OUString &/*rName*/)
void XMLParaContext::characters(const OUString &rChars)
{
librevenge::RVNGPropertyList aPropertyList;
if (!m_aStyleName.isEmpty())
{
// Reference to an automatic style, try to look it up.
auto itStyle = mrImport.GetAutomaticTextStyles().find(m_aStyleName);
if (itStyle != mrImport.GetAutomaticTextStyles().end())
{
// Found an automatic text style.
librevenge::RVNGPropertyList::Iter itProp(itStyle->second);
for (itProp.rewind(); itProp.next();)
aPropertyList.insert(itProp.key(), itProp()->clone());
}
}
mrImport.GetGenerator().openSpan(aPropertyList);
OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
mrImport.GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
mrImport.GetGenerator().closeSpan();
}
} // namespace exp

View File

@@ -28,6 +28,9 @@ public:
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;
void SAL_CALL characters(const OUString &rChars) override;
private:
OUString m_aStyleName;
};
} // namespace exp

View File

@@ -42,7 +42,7 @@ void XMLParagraphPropertiesContext::startElement(const OUString &/*rName*/, cons
{
OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8);
OString sValue = OUStringToOString(xAttribs->getValueByIndex(i), RTL_TEXTENCODING_UTF8);
mrStyle.GetPropertyList().insert(sName.getStr(), sValue.getStr());
mrStyle.GetParagraphPropertyList().insert(sName.getStr(), sValue.getStr());
}
}
@@ -70,7 +70,7 @@ void XMLTextPropertiesContext::startElement(const OUString &/*rName*/, const css
{
OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8);
OString sValue = OUStringToOString(xAttribs->getValueByIndex(i), RTL_TEXTENCODING_UTF8);
mrStyle.GetPropertyList().insert(sName.getStr(), sValue.getStr());
mrStyle.GetTextPropertyList().insert(sName.getStr(), sValue.getStr());
}
}
@@ -94,10 +94,9 @@ void XMLStyleContext::startElement(const OUString &/*rName*/, const css::uno::Re
{
const OUString &rAttributeName = xAttribs->getNameByIndex(i);
if (rAttributeName == "style:name")
{
m_aName = xAttribs->getValueByIndex(i);
break;
}
else if (rAttributeName == "style:family")
m_aFamily = xAttribs->getValueByIndex(i);
}
}
@@ -106,12 +105,20 @@ void XMLStyleContext::endElement(const OUString &/*rName*/)
if (m_aName.isEmpty())
return;
mrImport.GetAutomaticStyles()[m_aName] = m_aPropertyList;
if (m_aFamily == "text" || m_aFamily == "paragraph")
mrImport.GetAutomaticTextStyles()[m_aName] = m_aTextPropertyList;
if (m_aFamily == "paragraph")
mrImport.GetAutomaticParagraphStyles()[m_aName] = m_aParagraphPropertyList;
}
librevenge::RVNGPropertyList &XMLStyleContext::GetPropertyList()
librevenge::RVNGPropertyList &XMLStyleContext::GetTextPropertyList()
{
return m_aPropertyList;
return m_aTextPropertyList;
}
librevenge::RVNGPropertyList &XMLStyleContext::GetParagraphPropertyList()
{
return m_aParagraphPropertyList;
}
} // namespace exp

View File

@@ -29,11 +29,14 @@ public:
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;
librevenge::RVNGPropertyList &GetPropertyList();
librevenge::RVNGPropertyList &GetTextPropertyList();
librevenge::RVNGPropertyList &GetParagraphPropertyList();
private:
OUString m_aName;
librevenge::RVNGPropertyList m_aPropertyList;
OUString m_aFamily;
librevenge::RVNGPropertyList m_aTextPropertyList;
librevenge::RVNGPropertyList m_aParagraphPropertyList;
};
} // namespace exp

View File

@@ -84,9 +84,14 @@ librevenge::RVNGTextInterface &XMLImport::GetGenerator() const
return mrGenerator;
}
std::map<OUString, librevenge::RVNGPropertyList> &XMLImport::GetAutomaticStyles()
std::map<OUString, librevenge::RVNGPropertyList> &XMLImport::GetAutomaticTextStyles()
{
return maAutomaticStyles;
return maAutomaticTextStyles;
}
std::map<OUString, librevenge::RVNGPropertyList> &XMLImport::GetAutomaticParagraphStyles()
{
return maAutomaticParagraphStyles;
}
void XMLImport::startDocument()

View File

@@ -35,7 +35,8 @@ class XMLImport : public cppu::WeakImplHelper
{
librevenge::RVNGTextInterface &mrGenerator;
std::stack< rtl::Reference<XMLImportContext> > maContexts;
std::map<OUString, librevenge::RVNGPropertyList> maAutomaticStyles;
std::map<OUString, librevenge::RVNGPropertyList> maAutomaticTextStyles;
std::map<OUString, librevenge::RVNGPropertyList> maAutomaticParagraphStyles;
public:
XMLImport(librevenge::RVNGTextInterface &rGenerator);
@@ -43,7 +44,8 @@ public:
XMLImportContext *CreateContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs);
librevenge::RVNGTextInterface &GetGenerator() const;
std::map<OUString, librevenge::RVNGPropertyList> &GetAutomaticStyles();
std::map<OUString, librevenge::RVNGPropertyList> &GetAutomaticTextStyles();
std::map<OUString, librevenge::RVNGPropertyList> &GetAutomaticParagraphStyles();
// XDocumentHandler
void SAL_CALL startDocument() override;