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:
@@ -52,6 +52,7 @@ public:
|
|||||||
void testEPUB2();
|
void testEPUB2();
|
||||||
void testPageBreakSplit();
|
void testPageBreakSplit();
|
||||||
void testSpanAutostyle();
|
void testSpanAutostyle();
|
||||||
|
void testParaAutostyleCharProps();
|
||||||
|
|
||||||
CPPUNIT_TEST_SUITE(EPUBExportTest);
|
CPPUNIT_TEST_SUITE(EPUBExportTest);
|
||||||
CPPUNIT_TEST(testOutlineLevel);
|
CPPUNIT_TEST(testOutlineLevel);
|
||||||
@@ -59,6 +60,7 @@ public:
|
|||||||
CPPUNIT_TEST(testEPUB2);
|
CPPUNIT_TEST(testEPUB2);
|
||||||
CPPUNIT_TEST(testPageBreakSplit);
|
CPPUNIT_TEST(testPageBreakSplit);
|
||||||
CPPUNIT_TEST(testSpanAutostyle);
|
CPPUNIT_TEST(testSpanAutostyle);
|
||||||
|
CPPUNIT_TEST(testParaAutostyleCharProps);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -190,6 +192,16 @@ void EPUBExportTest::testSpanAutostyle()
|
|||||||
assertXPath(mpXmlDoc, "//xhtml:p/xhtml:span[3]", "class", "span2");
|
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);
|
CPPUNIT_TEST_SUITE_REGISTRATION(EPUBExportTest);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||||
|
<style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" 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>
|
@@ -53,9 +53,9 @@ void XMLSpanContext::startElement(const OUString &/*rName*/, const css::uno::Ref
|
|||||||
const OUString &rAttributeValue = xAttribs->getValueByIndex(i);
|
const OUString &rAttributeValue = xAttribs->getValueByIndex(i);
|
||||||
if (rAttributeName == "text:style-name")
|
if (rAttributeName == "text:style-name")
|
||||||
{
|
{
|
||||||
// Reference to an automatic style, try to look it up.
|
// Reference to an automatic text style, try to look it up.
|
||||||
auto itStyle = mrImport.GetAutomaticStyles().find(rAttributeValue);
|
auto itStyle = mrImport.GetAutomaticTextStyles().find(rAttributeValue);
|
||||||
if (itStyle == mrImport.GetAutomaticStyles().end())
|
if (itStyle == mrImport.GetAutomaticTextStyles().end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Apply properties directly, librevenge has no notion of automatic styles.
|
// 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);
|
const OUString &rAttributeValue = xAttribs->getValueByIndex(i);
|
||||||
if (rAttributeName == "text:style-name")
|
if (rAttributeName == "text:style-name")
|
||||||
{
|
{
|
||||||
|
m_aStyleName = rAttributeValue;
|
||||||
|
|
||||||
// Reference to an automatic style, try to look it up.
|
// Reference to an automatic style, try to look it up.
|
||||||
auto itStyle = mrImport.GetAutomaticStyles().find(rAttributeValue);
|
auto itStyle = mrImport.GetAutomaticParagraphStyles().find(m_aStyleName);
|
||||||
if (itStyle == mrImport.GetAutomaticStyles().end())
|
if (itStyle == mrImport.GetAutomaticParagraphStyles().end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Apply properties directly, librevenge has no notion of automatic styles.
|
// Found an automatic paragraph style.
|
||||||
librevenge::RVNGPropertyList::Iter itProp(itStyle->second);
|
librevenge::RVNGPropertyList::Iter itProp(itStyle->second);
|
||||||
for (itProp.rewind(); itProp.next();)
|
for (itProp.rewind(); itProp.next();)
|
||||||
aPropertyList.insert(itProp.key(), itProp());
|
aPropertyList.insert(itProp.key(), itProp()->clone());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -180,8 +182,25 @@ void XMLParaContext::endElement(const OUString &/*rName*/)
|
|||||||
|
|
||||||
void XMLParaContext::characters(const OUString &rChars)
|
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);
|
OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
|
||||||
mrImport.GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
|
mrImport.GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
|
||||||
|
|
||||||
|
mrImport.GetGenerator().closeSpan();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace exp
|
} // namespace exp
|
||||||
|
@@ -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 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 endElement(const OUString &rName) override;
|
||||||
void SAL_CALL characters(const OUString &rChars) override;
|
void SAL_CALL characters(const OUString &rChars) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
OUString m_aStyleName;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace exp
|
} // namespace exp
|
||||||
|
@@ -42,7 +42,7 @@ void XMLParagraphPropertiesContext::startElement(const OUString &/*rName*/, cons
|
|||||||
{
|
{
|
||||||
OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8);
|
OString sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8);
|
||||||
OString sValue = OUStringToOString(xAttribs->getValueByIndex(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 sName = OUStringToOString(xAttribs->getNameByIndex(i), RTL_TEXTENCODING_UTF8);
|
||||||
OString sValue = OUStringToOString(xAttribs->getValueByIndex(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);
|
const OUString &rAttributeName = xAttribs->getNameByIndex(i);
|
||||||
if (rAttributeName == "style:name")
|
if (rAttributeName == "style:name")
|
||||||
{
|
|
||||||
m_aName = xAttribs->getValueByIndex(i);
|
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())
|
if (m_aName.isEmpty())
|
||||||
return;
|
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
|
} // namespace exp
|
||||||
|
@@ -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 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 endElement(const OUString &rName) override;
|
||||||
|
|
||||||
librevenge::RVNGPropertyList &GetPropertyList();
|
librevenge::RVNGPropertyList &GetTextPropertyList();
|
||||||
|
librevenge::RVNGPropertyList &GetParagraphPropertyList();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OUString m_aName;
|
OUString m_aName;
|
||||||
librevenge::RVNGPropertyList m_aPropertyList;
|
OUString m_aFamily;
|
||||||
|
librevenge::RVNGPropertyList m_aTextPropertyList;
|
||||||
|
librevenge::RVNGPropertyList m_aParagraphPropertyList;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace exp
|
} // namespace exp
|
||||||
|
@@ -84,9 +84,14 @@ librevenge::RVNGTextInterface &XMLImport::GetGenerator() const
|
|||||||
return mrGenerator;
|
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()
|
void XMLImport::startDocument()
|
||||||
|
@@ -35,7 +35,8 @@ class XMLImport : public cppu::WeakImplHelper
|
|||||||
{
|
{
|
||||||
librevenge::RVNGTextInterface &mrGenerator;
|
librevenge::RVNGTextInterface &mrGenerator;
|
||||||
std::stack< rtl::Reference<XMLImportContext> > maContexts;
|
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:
|
public:
|
||||||
XMLImport(librevenge::RVNGTextInterface &rGenerator);
|
XMLImport(librevenge::RVNGTextInterface &rGenerator);
|
||||||
@@ -43,7 +44,8 @@ public:
|
|||||||
XMLImportContext *CreateContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs);
|
XMLImportContext *CreateContext(const OUString &rName, const css::uno::Reference<css::xml::sax::XAttributeList> &xAttribs);
|
||||||
|
|
||||||
librevenge::RVNGTextInterface &GetGenerator() const;
|
librevenge::RVNGTextInterface &GetGenerator() const;
|
||||||
std::map<OUString, librevenge::RVNGPropertyList> &GetAutomaticStyles();
|
std::map<OUString, librevenge::RVNGPropertyList> &GetAutomaticTextStyles();
|
||||||
|
std::map<OUString, librevenge::RVNGPropertyList> &GetAutomaticParagraphStyles();
|
||||||
|
|
||||||
// XDocumentHandler
|
// XDocumentHandler
|
||||||
void SAL_CALL startDocument() override;
|
void SAL_CALL startDocument() override;
|
||||||
|
Reference in New Issue
Block a user