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

Miklos Vajna vmiklos at collabora.co.uk
Tue Jul 29 09:55:49 PDT 2014


 sw/qa/extras/ooxmlexport/data/paragraph-sdt.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport.cxx         |   18 ++---
 sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx    |   10 +++
 sw/source/filter/ww8/docxattributeoutput.cxx     |   70 ++++++++++++++++++++---
 sw/source/filter/ww8/docxattributeoutput.hxx     |    4 +
 writerfilter/source/dmapper/DomainMapper.cxx     |    7 +-
 writerfilter/source/dmapper/SdtHelper.cxx        |    1 
 writerfilter/source/dmapper/SdtHelper.hxx        |   12 +++
 8 files changed, 104 insertions(+), 18 deletions(-)

New commits:
commit 28a315694348c4d1a4fd9aea7e720b3e821e8eb3
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Tue Jul 29 17:56:08 2014 +0200

    DOCX filter: map <w:sdt> outside paragraphs to paragraph properties
    
    Previously the type of the SDT was used to decide if the SDT will be a
    character or paragraph property. Improve this situation by always
    mapping <w:sdt> elements outside paragraph to paragraph properties.
    
    In practice, this means that if the SDT was a rectangle (as it wasn't
    only around a run), then it remains so, while previously it could become
    a polygon instead (when painted).
    
    Fix several testcases that tested that a <w:sdt> outside a paragraph is
    exported as a character property.
    
    Change-Id: Ia26c1a4cf6bc553b46224e4b17ee40725c5f3622

diff --git a/sw/qa/extras/ooxmlexport/data/paragraph-sdt.docx b/sw/qa/extras/ooxmlexport/data/paragraph-sdt.docx
new file mode 100644
index 0000000..c86f599
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/paragraph-sdt.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index 77d8b4c..207ad5b 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -2603,9 +2603,9 @@ DECLARE_OOXMLEXPORT_TEST(testCheckBoxControl, "checkbox-control.docx")
     xmlDocPtr pXmlDoc = parseExport("word/document.xml");
     if (!pXmlDoc)
         return;
-    assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w14:checkbox/w14:checked", "val", "1");
-    assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w14:checkbox/w14:checkedState", "val", "2612");
-    assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w14:checkbox/w14:uncheckedState", "val", "2610");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w14:checkbox/w14:checked", "val", "1");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w14:checkbox/w14:checkedState", "val", "2612");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w14:checkbox/w14:uncheckedState", "val", "2610");
 
     // TODO: import control and add a check here
 }
@@ -2664,7 +2664,7 @@ DECLARE_OOXMLEXPORT_TEST(testSdtContent, "SdtContent.docx")
     xmlDocPtr pXmlDoc = parseExport("word/header1.xml");
     if (!pXmlDoc)
        return;
-    assertXPath(pXmlDoc, "/w:hdr[1]/w:p[1]/w:sdt[1]/w:sdtContent[1]/w:del[1]");
+    assertXPath(pXmlDoc, "/w:hdr[1]/w:sdt[1]/w:sdtContent[1]/w:p[1]/w:del[1]");
 }
 
 DECLARE_OOXMLEXPORT_TEST(testFdo76016, "fdo76016.docx")
@@ -2749,8 +2749,8 @@ DECLARE_OOXMLEXPORT_TEST(testSimpleSdts, "simple-sdts.docx")
     if (!pXmlDoc)
        return;
 
-    assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:sdt/w:sdtPr/w:text", 1);
-    assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:sdt/w:sdtPr/w:id", 1);
+    assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:text", 1);
+    assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:id", 3);
     assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:picture", 1);
     assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:group", 1);
     assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:citation", 1);
@@ -2797,8 +2797,8 @@ DECLARE_OOXMLEXPORT_TEST(testAuthorPropertySdt, "author-property.docx")
     if (!pXmlDoc)
        return;
 
-    assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dataBinding", "xpath", "/ns1:coreProperties[1]/ns0:creator[1]");
-    assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dataBinding", "storeItemID","{6C3C8BC8-F283-45AE-878A-BAB7291924A1}");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:dataBinding", "xpath", "/ns1:coreProperties[1]/ns0:creator[1]");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:dataBinding", "storeItemID","{6C3C8BC8-F283-45AE-878A-BAB7291924A1}");
     // FIXME: the next property doesn't match, though it's correct in theory. A bug in assertXPath?
     // assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:dataBinding", "prefixMappings",
     //            "xmlns:ns0='http://purl.org/dc/elements/1.1/' xmlns:ns1='http://schemas.openxmlformats.org/package/2006/metadata/core-properties'");
@@ -3366,7 +3366,7 @@ DECLARE_OOXMLEXPORT_TEST(testSdtAlias, "sdt-alias.docx")
         return;
 
     // <w:alias> was completely missing.
-    assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:alias", "val", "Subtitle");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:sdt/w:sdtPr/w:alias", "val", "Subtitle");
 }
 
 DECLARE_OOXMLEXPORT_TEST(testSdtDateCharformat, "sdt-date-charformat.docx")
diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
index 5d2732b..9b4b380 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
@@ -510,6 +510,16 @@ DECLARE_OOXMLEXPORT_TEST(testSdtCitationRun, "sdt-citation-run.docx")
     }
 }
 
+DECLARE_OOXMLEXPORT_TEST(testParagraphSdt, "paragraph-sdt.docx")
+{
+    // The problem was that the SDT was around the run only, not the whole paragraph.
+    if (xmlDocPtr pXmlDoc = parseExport())
+    {
+        // The path to w:sdt contained a w:p.
+        assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr/w:tc/w:sdt");
+    }
+}
+
 #endif
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 8eb11f8..ec65d8b 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -518,15 +518,15 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT
     }
 
     m_pSerializer->endElementNS( XML_w, XML_p );
-    OUString aParagraphSdtPrAlias;
     if( !m_bAnchorLinkedToNode )
-        WriteSdtBlock( m_nParagraphSdtPrToken, m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs, aParagraphSdtPrAlias, /*bPara=*/true );
+        WriteSdtBlock( m_nParagraphSdtPrToken, m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs, m_aParagraphSdtPrAlias, /*bPara=*/true );
     else
     {
         //These should be written out to the actual Node and not to the anchor.
         //Clear them as they will be repopulated when the node is processed.
         m_nParagraphSdtPrToken = 0;
-        lcl_deleteAndResetTheLists( m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs, aParagraphSdtPrAlias );
+        m_bParagraphSdtHasId = false;
+        lcl_deleteAndResetTheLists( m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs, m_aParagraphSdtPrAlias );
     }
 
     //sdtcontent is written so Set m_bParagraphHasDrawing to false
@@ -588,13 +588,14 @@ void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken,
 
             m_pSerializer->endElement( nSdtPrToken );
         }
-        else if( nSdtPrToken == FSNS( XML_w, XML_id ) )
+        else if( (nSdtPrToken > 0) && !(m_bRunTextIsOn && m_rExport.SdrExporter().IsParagraphHasDrawing()))
+            m_pSerializer->singleElement( nSdtPrToken, FSEND );
+
+        if( nSdtPrToken == FSNS( XML_w, XML_id ) || ( bPara && m_bParagraphSdtHasId ) )
             //Word won't open a document with an empty id tag, we fill it with a random number
-            m_pSerializer->singleElement( nSdtPrToken,
+            m_pSerializer->singleElementNS(XML_w, XML_id,
                                           FSNS(XML_w, XML_val), OString::number( rand() ),
                                           FSEND );
-        else if( (nSdtPrToken > 0) && !(m_bRunTextIsOn && m_rExport.SdrExporter().IsParagraphHasDrawing()))
-            m_pSerializer->singleElement( nSdtPrToken, FSEND );
 
         if(( pSdtPrDataBindingAttrs ) && !m_rExport.SdrExporter().IsParagraphHasDrawing())
         {
@@ -7663,6 +7664,60 @@ void DocxAttributeOutput::ParaGrabBag(const SfxGrabBagItem& rItem)
                     m_nParagraphSdtPrToken = FSNS( XML_w, XML_citation );
                 else if (aPropertyValue.Name == "ooxml:CT_SdtPr_group")
                     m_nParagraphSdtPrToken = FSNS( XML_w, XML_group );
+                else if (aPropertyValue.Name == "ooxml:CT_SdtPr_text")
+                    m_nParagraphSdtPrToken = FSNS(XML_w, XML_text);
+                else if (aPropertyValue.Name == "ooxml:CT_SdtPr_dataBinding" && !m_pParagraphSdtPrDataBindingAttrs)
+                {
+                    uno::Sequence<beans::PropertyValue> aGrabBag;
+                    aPropertyValue.Value >>= aGrabBag;
+                    for (sal_Int32 j = 0; j < aGrabBag.getLength(); ++j)
+                    {
+                        OUString sValue = aGrabBag[j].Value.get<OUString>();
+                        if (aGrabBag[j].Name == "ooxml:CT_DataBinding_prefixMappings")
+                            AddToAttrList( m_pParagraphSdtPrDataBindingAttrs,
+                                           FSNS( XML_w, XML_prefixMappings ),
+                                           rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
+                        else if (aGrabBag[j].Name == "ooxml:CT_DataBinding_xpath")
+                            AddToAttrList( m_pParagraphSdtPrDataBindingAttrs,
+                                           FSNS( XML_w, XML_xpath ),
+                                           rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
+                        else if (aGrabBag[j].Name == "ooxml:CT_DataBinding_storeItemID")
+                            AddToAttrList( m_pParagraphSdtPrDataBindingAttrs,
+                                           FSNS( XML_w, XML_storeItemID ),
+                                           rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
+                    }
+                }
+                else if (aPropertyValue.Name == "ooxml:CT_SdtPr_alias" && m_aParagraphSdtPrAlias.isEmpty())
+                {
+                    if (!(aPropertyValue.Value >>= m_aParagraphSdtPrAlias))
+                        SAL_WARN("sw.ww8", "DocxAttributeOutput::ParaGrabBag: unexpected sdt alias value");
+                }
+                else if (aPropertyValue.Name == "ooxml:CT_SdtPr_checkbox")
+                {
+                    m_nParagraphSdtPrToken = FSNS( XML_w14, XML_checkbox );
+                    uno::Sequence<beans::PropertyValue> aGrabBag;
+                    aPropertyValue.Value >>= aGrabBag;
+                    for (sal_Int32 j=0; j < aGrabBag.getLength(); ++j)
+                    {
+                        OUString sValue = aGrabBag[j].Value.get<OUString>();
+                        if (aGrabBag[j].Name == "ooxml:CT_SdtCheckbox_checked")
+                            AddToAttrList( m_pParagraphSdtPrTokenChildren,
+                                           FSNS( XML_w14, XML_checked ),
+                                           rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
+                        else if (aGrabBag[j].Name == "ooxml:CT_SdtCheckbox_checkedState")
+                            AddToAttrList( m_pParagraphSdtPrTokenChildren,
+                                           FSNS( XML_w14, XML_checkedState ),
+                                           rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
+                        else if (aGrabBag[j].Name == "ooxml:CT_SdtCheckbox_uncheckedState")
+                            AddToAttrList( m_pParagraphSdtPrTokenChildren,
+                                           FSNS( XML_w14, XML_uncheckedState ),
+                                           rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
+                    }
+                }
+                else if (aPropertyValue.Name == "ooxml:CT_SdtPr_id")
+                    m_bParagraphSdtHasId = true;
+                else
+                    SAL_INFO("sw.ww8", "DocxAttributeOutput::ParaGrabBag: unhandled SdtPr grab bag property " << aPropertyValue.Name);
             }
         }
         else
@@ -7927,6 +7982,7 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri
     , m_nRunSdtPrToken(0)
     , m_pRunSdtPrTokenChildren(NULL)
     , m_pRunSdtPrDataBindingAttrs(NULL)
+    , m_bParagraphSdtHasId(false)
 {
 }
 
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index 04770c5..ff4ed70 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -897,7 +897,11 @@ private:
     sal_Int32 m_nRunSdtPrToken;
     ::sax_fastparser::FastAttributeList *m_pRunSdtPrTokenChildren;
     ::sax_fastparser::FastAttributeList *m_pRunSdtPrDataBindingAttrs;
+    /// Value of the <w:alias> paragraph SDT element.
+    OUString m_aParagraphSdtPrAlias;
     OUString m_aRunSdtPrAlias;
+    /// Currently paragraph SDT has a <w:id> child element.
+    bool m_bParagraphSdtHasId;
 
     std::map<sal_uInt16, css::table::BorderLine2> m_aTableStyleConf;
 
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index c32d86a..b305afd 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -2371,6 +2371,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, PropertyMapPtr rContext )
         }
         else
             m_pImpl->m_pSdtHelper->appendToInteropGrabBag(getInteropGrabBag());
+        m_pImpl->m_pSdtHelper->setOutsideAParagraph(m_pImpl->IsOutsideAParagraph());
         m_pImpl->disableInteropGrabBag();
     }
     break;
@@ -2669,6 +2670,8 @@ void DomainMapper::lcl_endShape( )
 
         lcl_endParagraphGroup();
         m_pImpl->PopShapeContext( );
+        // A shape is always inside a shape (anchored or inline).
+        m_pImpl->SetIsOutsideAParagraph(false);
     }
 }
 
@@ -2833,12 +2836,12 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len)
     {
         // there are unsupported SDT properties in the document
         // save them in the paragraph interop grab bag
-        if(m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_checkbox") ||
+        if((m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_checkbox") ||
                 m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_text") ||
                 m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_dataBinding") ||
                 m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_citation") ||
                 (m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_id") &&
-                        m_pImpl->m_pSdtHelper->getInteropGrabBagSize() == 1))
+                        m_pImpl->m_pSdtHelper->getInteropGrabBagSize() == 1)) && !m_pImpl->m_pSdtHelper->isOutsideAParagraph())
         {
             PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_CHARACTER);
 
diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx
index ce57d60..bf268a3 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -70,6 +70,7 @@ awt::Size lcl_getOptimalWidth(StyleSheetTablePtr pStyleSheet, OUString& rDefault
 SdtHelper::SdtHelper(DomainMapper_Impl& rDM_Impl)
     : m_rDM_Impl(rDM_Impl)
     , m_bHasElements(false)
+    , m_bOutsideAParagraph(false)
 {
 }
 
diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx
index f4f56ab..c8d59bc 100644
--- a/writerfilter/source/dmapper/SdtHelper.hxx
+++ b/writerfilter/source/dmapper/SdtHelper.hxx
@@ -60,6 +60,8 @@ class SdtHelper
     com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> m_aGrabBag;
 
     bool m_bHasElements;
+    /// The last stored SDT element is outside paragraphs.
+    bool m_bOutsideAParagraph;
 
     /// Create and append the drawing::XControlShape, containing the various models.
     void createControlShape(css::awt::Size aSize, css::uno::Reference<css::awt::XControlModel> const&);
@@ -94,6 +96,16 @@ public:
         return m_bHasElements;
     }
 
+    void setOutsideAParagraph(bool bOutsideAParagraph)
+    {
+        m_bOutsideAParagraph = bOutsideAParagraph;
+    }
+
+    bool isOutsideAParagraph()
+    {
+        return m_bOutsideAParagraph;
+    }
+
     /// Create drop-down control from w:sdt's w:dropDownList.
     void createDropDownControl();
     /// Create date control from w:sdt's w:date.


More information about the Libreoffice-commits mailing list