[Libreoffice-commits] core.git: writerperfect/qa writerperfect/source

Miklos Vajna vmiklos at collabora.co.uk
Wed Sep 6 16:09:19 UTC 2017


 writerperfect/qa/unit/EPUBExportTest.cxx                                  |   41 +++++++
 writerperfect/qa/unit/data/writer/epubexport/named-style-inheritance.fodt |   39 +++++++
 writerperfect/source/writer/exp/txtparai.cxx                              |   54 ++++++----
 writerperfect/source/writer/exp/txtstyli.cxx                              |   11 +-
 4 files changed, 126 insertions(+), 19 deletions(-)

New commits:
commit fe4c6063ec493c986f810ba676e2b12fe7dab7a9
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Sep 6 15:35:40 2017 +0200

    EPUB export: handle style parents for named styles
    
    Character / paragraph formatting from a style hierarchy should be OK
    now. Also this time test the actual CSS contents, not just that the rule
    name for two paragraphs or spans differs.
    
    Change-Id: I18a9c11aaf16bb3c4b462415b5e819f16de0893c
    Reviewed-on: https://gerrit.libreoffice.org/41993
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Jenkins <ci at libreoffice.org>

diff --git a/writerperfect/qa/unit/EPUBExportTest.cxx b/writerperfect/qa/unit/EPUBExportTest.cxx
index 1b57655180b0..7b5de434bf8f 100644
--- a/writerperfect/qa/unit/EPUBExportTest.cxx
+++ b/writerperfect/qa/unit/EPUBExportTest.cxx
@@ -47,6 +47,8 @@ public:
     void createDoc(const OUString &rFile, const uno::Sequence<beans::PropertyValue> &rFilterData);
     /// Returns an XML representation of the stream named rName in the exported package.
     xmlDocPtr parseExport(const OUString &rName);
+    /// Loads a CSS representation of the stream named rName in the exported package into rTree.
+    void parseCssExport(const OUString &rName, std::map< OString, std::vector<OString> > &rTree);
     void testOutlineLevel();
     void testMimetype();
     void testEPUB2();
@@ -56,6 +58,7 @@ public:
     void testMeta();
     void testParaNamedstyle();
     void testCharNamedstyle();
+    void testNamedStyleInheritance();
 
     CPPUNIT_TEST_SUITE(EPUBExportTest);
     CPPUNIT_TEST(testOutlineLevel);
@@ -67,6 +70,7 @@ public:
     CPPUNIT_TEST(testMeta);
     CPPUNIT_TEST(testParaNamedstyle);
     CPPUNIT_TEST(testCharNamedstyle);
+    CPPUNIT_TEST(testNamedStyleInheritance);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -122,6 +126,25 @@ xmlDocPtr EPUBExportTest::parseExport(const OUString &rName)
     return parseXmlStream(pStream.get());
 }
 
+void EPUBExportTest::parseCssExport(const OUString &rName, std::map< OString, std::vector<OString> > &rTree)
+{
+    uno::Reference<io::XInputStream> xInputStream(mxZipFile->getByName(rName), uno::UNO_QUERY);
+    std::shared_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+
+    // Minimal CSS handler till orcus is up to our needs.
+    OString aLine;
+    OString aRuleName;
+    while (!pStream->IsEof())
+    {
+        pStream->ReadLine(aLine);
+        if (aLine.endsWith("{"))
+            // '.name {' -> 'name'
+            aRuleName = aLine.copy(1, aLine.getLength() - 3);
+        else if (aLine.endsWith(";"))
+            rTree[aRuleName].push_back(aLine);
+    }
+}
+
 void EPUBExportTest::testOutlineLevel()
 {
     createDoc("outline-level.fodt", {});
@@ -246,6 +269,24 @@ void EPUBExportTest::testCharNamedstyle()
     assertXPath(mpXmlDoc, "//xhtml:p/xhtml:span[2]", "class", "span1");
 }
 
+void EPUBExportTest::testNamedStyleInheritance()
+{
+    createDoc("named-style-inheritance.fodt", {});
+
+    // Find the CSS rule for the blue text.
+    mpXmlDoc = parseExport("OEBPS/sections/section0001.xhtml");
+    OUString aBlue = getXPath(mpXmlDoc, "//xhtml:p[2]/xhtml:span[2]", "class");
+
+    std::map< OString, std::vector<OString> > aTree;
+    parseCssExport("OEBPS/styles/stylesheet.css", aTree);
+    CPPUNIT_ASSERT(aTree.find(aBlue.toUtf8()) != aTree.end());
+    const std::vector<OString> &rRule = aTree[aBlue.toUtf8()];
+    CPPUNIT_ASSERT(std::find(rRule.begin(), rRule.end(), "  color: #0000ff;") != rRule.end());
+    // This failed, the span only had the properties from its style, but not
+    // from the style's parent(s).
+    CPPUNIT_ASSERT(std::find(rRule.begin(), rRule.end(), "  font-family: 'Liberation Mono';") != rRule.end());
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(EPUBExportTest);
 
 }
diff --git a/writerperfect/qa/unit/data/writer/epubexport/named-style-inheritance.fodt b/writerperfect/qa/unit/data/writer/epubexport/named-style-inheritance.fodt
new file mode 100644
index 000000000000..2bd6197774c5
--- /dev/null
+++ b/writerperfect/qa/unit/data/writer/epubexport/named-style-inheritance.fodt
@@ -0,0 +1,39 @@
+<?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:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oas
 is:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
+  <office:font-face-decls>
+    <style:font-face style:name="Liberation Mono" svg:font-family="'Liberation Mono'" style:font-family-generic="modern" style:font-pitch="fixed"/>
+    <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:styles>
+    <style:style style:name="Heading" style:family="paragraph" style:class="text">
+      <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" fo:keep-with-next="always"/>
+      <style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="14pt"/>
+    </style:style>
+    <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:default-outline-level="1" style:class="text">
+    </style:style>
+    <style:style style:name="Blue_20_Source_20_Text" style:display-name="Blue Source Text" style:family="text" style:parent-style-name="Source_20_Text">
+      <style:text-properties fo:color="#0000ff"/>
+    </style:style>
+    <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text">
+      <style:text-properties style:font-name="Liberation Mono" fo:font-family="'Liberation Mono'" style:font-family-generic="modern" style:font-pitch="fixed"/>
+    </style:style>
+  </office:styles>
+  <office:automatic-styles>
+    <style:page-layout style:name="pm1">
+      <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm">
+      </style:page-layout-properties>
+      <style:header-style/>
+      <style:footer-style/>
+    </style:page-layout>
+  </office:automatic-styles>
+  <office:master-styles>
+    <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+  </office:master-styles>
+  <office:body>
+    <office:text>
+      <text:h text:style-name="Heading_20_1" text:outline-level="1">Heading 1</text:h>
+      <text:p>Text Body<text:span text:style-name="Blue_20_Source_20_Text">blue</text:span></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 f2df54d0e1b0..9658d79f48b9 100644
--- a/writerperfect/source/writer/exp/txtparai.cxx
+++ b/writerperfect/source/writer/exp/txtparai.cxx
@@ -17,32 +17,52 @@ using namespace com::sun::star;
 namespace
 {
 
-/// Looks for rName in rAutomaticStyles (and failing that, in rNamedStyles) and fills rPropertyList based on that.
+/// Looks for rName in rAutomaticStyles (and failing that, in rNamedStyles) and
+/// fills rPropertyList based on that.
+void FillStyles(const OUString &rName,
+                std::map<OUString, librevenge::RVNGPropertyList> &rAutomaticStyles,
+                std::map<OUString, librevenge::RVNGPropertyList> &rNamedStyles,
+                librevenge::RVNGPropertyList &rPropertyList);
+
+/// Looks for rName in rStyles and fills rPropertyList based on that
+/// (rAutomaticStyles and rNamedStyles are a list of possible parents).
 void FillStyle(const OUString &rName,
-               std::map<OUString, librevenge::RVNGPropertyList> &rNamedStyles,
+               std::map<OUString, librevenge::RVNGPropertyList> &rStyles,
                std::map<OUString, librevenge::RVNGPropertyList> &rAutomaticStyles,
+               std::map<OUString, librevenge::RVNGPropertyList> &rNamedStyles,
                librevenge::RVNGPropertyList &rPropertyList)
 {
-    auto itStyle = rAutomaticStyles.find(rName);
-    if (itStyle != rAutomaticStyles.end())
-    {
-        // Apply properties from automatic style.
-        librevenge::RVNGPropertyList::Iter itProp(itStyle->second);
-        for (itProp.rewind(); itProp.next();)
-            rPropertyList.insert(itProp.key(), itProp()->clone());
+    auto itStyle = rStyles.find(rName);
+    if (itStyle == rStyles.end())
         return;
+
+    const librevenge::RVNGPropertyList &rStyle = itStyle->second;
+    if (rStyle["style:parent-style-name"])
+    {
+        // Style has a parent.
+        OUString aParent = OStringToOUString(rStyle["style:parent-style-name"]->getStr().cstr(), RTL_TEXTENCODING_UTF8);
+        if (!aParent.isEmpty())
+            FillStyles(aParent, rAutomaticStyles, rNamedStyles, rPropertyList);
     }
 
-    itStyle = rNamedStyles.find(rName);
-    if (itStyle != rNamedStyles.end())
+    // Apply properties from named style.
+    librevenge::RVNGPropertyList::Iter itProp(rStyle);
+    for (itProp.rewind(); itProp.next();)
     {
-        // Apply properties from named style.
-        librevenge::RVNGPropertyList::Iter itProp(itStyle->second);
-        for (itProp.rewind(); itProp.next();)
+        if (OString("style:parent-style-name") != itProp.key())
             rPropertyList.insert(itProp.key(), itProp()->clone());
     }
 }
 
+void FillStyles(const OUString &rName,
+                std::map<OUString, librevenge::RVNGPropertyList> &rAutomaticStyles,
+                std::map<OUString, librevenge::RVNGPropertyList> &rNamedStyles,
+                librevenge::RVNGPropertyList &rPropertyList)
+{
+    FillStyle(rName, rAutomaticStyles, rAutomaticStyles, rNamedStyles, rPropertyList);
+    FillStyle(rName, rNamedStyles, rAutomaticStyles, rNamedStyles, rPropertyList);
+}
+
 }
 
 namespace writerperfect
@@ -83,7 +103,7 @@ void XMLSpanContext::startElement(const OUString &/*rName*/, const css::uno::Ref
         const OUString &rAttributeName = xAttribs->getNameByIndex(i);
         const OUString &rAttributeValue = xAttribs->getValueByIndex(i);
         if (rAttributeName == "text:style-name")
-            FillStyle(rAttributeValue, mrImport.GetAutomaticTextStyles(), mrImport.GetTextStyles(), aPropertyList);
+            FillStyles(rAttributeValue, mrImport.GetAutomaticTextStyles(), mrImport.GetTextStyles(), aPropertyList);
         else
         {
             OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8);
@@ -174,7 +194,7 @@ void XMLParaContext::startElement(const OUString &/*rName*/, const css::uno::Ref
         if (rAttributeName == "text:style-name")
         {
             m_aStyleName = rAttributeValue;
-            FillStyle(m_aStyleName, mrImport.GetAutomaticParagraphStyles(), mrImport.GetParagraphStyles(), aPropertyList);
+            FillStyles(m_aStyleName, mrImport.GetAutomaticParagraphStyles(), mrImport.GetParagraphStyles(), aPropertyList);
         }
         else
         {
@@ -196,7 +216,7 @@ void XMLParaContext::characters(const OUString &rChars)
 {
     librevenge::RVNGPropertyList aPropertyList;
     if (!m_aStyleName.isEmpty())
-        FillStyle(m_aStyleName, mrImport.GetAutomaticTextStyles(), mrImport.GetTextStyles(), aPropertyList);
+        FillStyles(m_aStyleName, mrImport.GetAutomaticTextStyles(), mrImport.GetTextStyles(), aPropertyList);
     mrImport.GetGenerator().openSpan(aPropertyList);
 
     OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
diff --git a/writerperfect/source/writer/exp/txtstyli.cxx b/writerperfect/source/writer/exp/txtstyli.cxx
index a3e8395d4b43..420651a1ddb0 100644
--- a/writerperfect/source/writer/exp/txtstyli.cxx
+++ b/writerperfect/source/writer/exp/txtstyli.cxx
@@ -95,10 +95,17 @@ void XMLStyleContext::startElement(const OUString &/*rName*/, const css::uno::Re
     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")
-            m_aName = xAttribs->getValueByIndex(i);
+            m_aName = rAttributeValue;
         else if (rAttributeName == "style:family")
-            m_aFamily = xAttribs->getValueByIndex(i);
+            m_aFamily = rAttributeValue;
+
+        // Remember properties of the style itself, e.g. parent name.
+        OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8);
+        OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8);
+        m_aTextPropertyList.insert(sName.getStr(), sValue.getStr());
+        m_aParagraphPropertyList.insert(sName.getStr(), sValue.getStr());
     }
 }
 


More information about the Libreoffice-commits mailing list