[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.0' - sw/qa sw/source writerfilter/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Thu Jul 4 07:03:29 UTC 2019


 sw/qa/extras/ooxmlexport/data/image-comment-at-char.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport11.cxx               |   18 ++++++
 sw/source/filter/ww8/docxexport.cxx                      |    4 -
 sw/source/filter/ww8/docxexport.hxx                      |    2 
 sw/source/filter/ww8/rtfexport.cxx                       |    5 +
 sw/source/filter/ww8/rtfexport.hxx                       |    3 -
 sw/source/filter/ww8/wrtw8nds.cxx                        |   42 ++++++++++++---
 sw/source/filter/ww8/wrtww8.cxx                          |    4 -
 sw/source/filter/ww8/wrtww8.hxx                          |   11 ++-
 writerfilter/source/dmapper/DomainMapper_Impl.cxx        |   19 ++++++
 10 files changed, 88 insertions(+), 20 deletions(-)

New commits:
commit 9ffd2d9ade3e9c4ecf50a1948637c902486f88bf
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Tue Jul 2 16:26:03 2019 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Jul 4 09:02:48 2019 +0200

    sw comments on frames: fix DOCX handling
    
    We used to ignore annotation marks which just cover the comment anchor
    since commit fff019debf14a0bf8cd358591a686191347f1542 (MSWordExportBase:
    ignore empty annotation marks, 2014-09-17), but this means comments on
    images are lost.
    
    Pass around SwWW8AttrIter, so we can decide if we have a relevant
    at-char anchored frame in MSWordExportBase::GetAnnotationMarks(),
    without iterating over all frames in the document, which would be slow
    for large documents.
    
    Regarding the import side, the only problem was that the empty comment
    range resulted in a loss of annotation marks; fix that by using a marker
    while inserting.
    
    (cherry picked from commit 7fa96a3e4bdd384ad411e0bdc4e7c3f2ab920279)
    
    Conflicts:
            sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
            sw/source/filter/ww8/docxexport.cxx
            sw/source/filter/ww8/docxexport.hxx
            sw/source/filter/ww8/rtfexport.cxx
            sw/source/filter/ww8/rtfexport.hxx
            sw/source/filter/ww8/wrtw8nds.cxx
            sw/source/filter/ww8/wrtww8.cxx
            sw/source/filter/ww8/wrtww8.hxx
            writerfilter/source/dmapper/DomainMapper_Impl.cxx
    
    Change-Id: I385677d74423bc05824dac4a12d1a991bb3983c4
    Reviewed-on: https://gerrit.libreoffice.org/75039
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    Tested-by: Miklos Vajna <vmiklos at collabora.com>

diff --git a/sw/qa/extras/ooxmlexport/data/image-comment-at-char.docx b/sw/qa/extras/ooxmlexport/data/image-comment-at-char.docx
new file mode 100644
index 000000000000..677464de49f7
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/image-comment-at-char.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index b8214f664e42..f77320436ea3 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -450,6 +450,24 @@ DECLARE_OOXMLEXPORT_TEST(testTdf123636_newlinePageBreak4, "tdf123636_newlinePage
     assertXPath(pDump, "/root/page[2]/body/txt[1]/Text", 0);
 }
 
+DECLARE_OOXMLEXPORT_TEST(testImageCommentAtChar, "image-comment-at-char.docx")
+{
+    uno::Reference<text::XTextRange> xPara = getParagraph(1);
+    CPPUNIT_ASSERT_EQUAL(OUString("Text"),
+                         getProperty<OUString>(getRun(xPara, 1), "TextPortionType"));
+    // Without the accompanying fix in place, this test would have failed with 'Expected:
+    // Annotation; Actual: Frame', i.e. the comment start before the image was lost.
+    CPPUNIT_ASSERT_EQUAL(OUString("Annotation"),
+                         getProperty<OUString>(getRun(xPara, 2), "TextPortionType"));
+    CPPUNIT_ASSERT_EQUAL(OUString("Frame"),
+                         getProperty<OUString>(getRun(xPara, 3), "TextPortionType"));
+    CPPUNIT_ASSERT_EQUAL(OUString("AnnotationEnd"),
+                         getProperty<OUString>(getRun(xPara, 4), "TextPortionType"));
+    CPPUNIT_ASSERT_EQUAL(OUString("Text"),
+                         getProperty<OUString>(getRun(xPara, 5), "TextPortionType"));
+}
+
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index becf669cf2fc..ccfce360f49c 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -187,13 +187,13 @@ void DocxExport::AppendBookmark( const OUString& rName )
     m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
 }
 
-void DocxExport::AppendAnnotationMarks( const SwTextNode& rNode, sal_Int32 nAktPos, sal_Int32 nLen )
+void DocxExport::AppendAnnotationMarks( const SwWW8AttrIter& rAttrs, sal_Int32 nAktPos, sal_Int32 nLen )
 {
     std::vector< OUString > aStarts;
     std::vector< OUString > aEnds;
 
     IMarkVector aMarks;
-    if ( GetAnnotationMarks( rNode, nAktPos, nAktPos + nLen, aMarks ) )
+    if ( GetAnnotationMarks( rAttrs, nAktPos, nAktPos + nLen, aMarks ) )
     {
         for ( IMarkVector::const_iterator it = aMarks.begin(), end = aMarks.end();
               it != end; ++it )
diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx
index 22b5dca7934e..f859a1e75278 100644
--- a/sw/source/filter/ww8/docxexport.hxx
+++ b/sw/source/filter/ww8/docxexport.hxx
@@ -141,7 +141,7 @@ public:
 
     virtual void AppendBookmark( const OUString& rName ) override;
 
-    virtual void AppendAnnotationMarks( const SwTextNode& rNode, sal_Int32 nAktPos, sal_Int32 nLen ) override;
+    virtual void AppendAnnotationMarks( const SwWW8AttrIter& rAttrs, sal_Int32 nAktPos, sal_Int32 nLen ) override;
 
     virtual void ExportGrfBullet(const SwTextNode&) override;
 
diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx
index 679b96ac9a77..e265f2618a06 100644
--- a/sw/source/filter/ww8/rtfexport.cxx
+++ b/sw/source/filter/ww8/rtfexport.cxx
@@ -131,13 +131,14 @@ void RtfExport::AppendBookmark(const OUString& rName)
     m_pAttrOutput->WriteBookmarks_Impl(aStarts, aEnds);
 }
 
-void RtfExport::AppendAnnotationMarks(const SwTextNode& rNode, sal_Int32 nAktPos, sal_Int32 nLen)
+void RtfExport::AppendAnnotationMarks(const SwWW8AttrIter& rAttrs, sal_Int32 nAktPos,
+                                      sal_Int32 nLen)
 {
     std::vector<OUString> aStarts;
     std::vector<OUString> aEnds;
 
     IMarkVector aMarks;
-    if (GetAnnotationMarks(rNode, nAktPos, nAktPos + nLen, aMarks))
+    if (GetAnnotationMarks(rAttrs, nAktPos, nAktPos + nLen, aMarks))
     {
         for (const auto& pMark : aMarks)
         {
diff --git a/sw/source/filter/ww8/rtfexport.hxx b/sw/source/filter/ww8/rtfexport.hxx
index b470ef593f30..ab86e9bdf794 100644
--- a/sw/source/filter/ww8/rtfexport.hxx
+++ b/sw/source/filter/ww8/rtfexport.hxx
@@ -73,7 +73,8 @@ public:
 
     void AppendBookmark(const OUString& rName) override;
 
-    void AppendAnnotationMarks(const SwTextNode& rNode, sal_Int32 nAktPos, sal_Int32 nLen) override;
+    void AppendAnnotationMarks(const SwWW8AttrIter& rAttrs, sal_Int32 nAktPos,
+                               sal_Int32 nLen) override;
 
     //For i120928,add an interface to export graphic of bullet
     void ExportGrfBullet(const SwTextNode& rNd) override;
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 9361943a7636..2ec8a8c90ef3 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -571,6 +571,21 @@ bool SwWW8AttrIter::IsAnchorLinkedToThisNode( sal_uLong nNodePos )
     return false ;
 }
 
+bool SwWW8AttrIter::HasFlysAt(sal_Int32 nSwPos) const
+{
+    for (const auto& rFly : maFlyFrames)
+    {
+        const SwPosition& rAnchor = rFly.GetPosition();
+        const sal_Int32 nPos = rAnchor.nContent.GetIndex();
+        if (nPos == nSwPos)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 FlyProcessingState SwWW8AttrIter::OutFlys(sal_Int32 nSwPos)
 {
     // collection point to first gather info about all of the potentially linked textboxes: to be analyzed later.
@@ -1934,7 +1949,7 @@ sal_Int32 MSWordExportBase::GetNextPos( SwWW8AttrIter const * aAttrIter, const S
     {
         GetSortedBookmarks( rNode, nAktPos, nNextBookmark - nAktPos );
         NearestBookmark( nNextBookmark, nAktPos, false );
-        GetSortedAnnotationMarks( rNode, nAktPos, nNextAnnotationMark - nAktPos );
+        GetSortedAnnotationMarks( *aAttrIter, nAktPos, nNextAnnotationMark - nAktPos );
         NearestAnnotationMark( nNextAnnotationMark, nAktPos, false );
     }
     return std::min( nNextPos, std::min( nNextBookmark, nNextAnnotationMark ) );
@@ -1988,11 +2003,11 @@ bool MSWordExportBase::GetBookmarks( const SwTextNode& rNd, sal_Int32 nStt,
     return ( rArr.size() > 0 );
 }
 
-bool MSWordExportBase::GetAnnotationMarks( const SwTextNode& rNd, sal_Int32 nStt,
+bool MSWordExportBase::GetAnnotationMarks( const SwWW8AttrIter& rAttrs, sal_Int32 nStt,
                     sal_Int32 nEnd, IMarkVector& rArr )
 {
     IDocumentMarkAccess* const pMarkAccess = m_pDoc->getIDocumentMarkAccess();
-    sal_uLong nNd = rNd.GetIndex( );
+    sal_uLong nNd = rAttrs.GetNode().GetIndex();
 
     const sal_Int32 nMarks = pMarkAccess->getAnnotationMarksCount();
     for ( sal_Int32 i = 0; i < nMarks; i++ )
@@ -2015,6 +2030,16 @@ bool MSWordExportBase::GetAnnotationMarks( const SwTextNode& rNd, sal_Int32 nStt
             // comment field, so ignore the annotation mark itself.
             bool bSingleChar = pMark->GetMarkStart().nNode == pMark->GetMarkEnd().nNode && nBStart + 1 == nBEnd;
 
+            if (bSingleChar)
+            {
+                if (rAttrs.HasFlysAt(nBStart))
+                {
+                    // There is content (an at-char anchored frame) between the annotation mark
+                    // start/end, so still emit range start/end.
+                    bSingleChar = false;
+                }
+            }
+
             if ( ( bIsStartOk || bIsEndOk ) && !bSingleChar )
             {
                 rArr.push_back( pMark );
@@ -2097,10 +2122,10 @@ void MSWordExportBase::NearestAnnotationMark( sal_Int32& rNearest, const sal_Int
     }
 }
 
-void MSWordExportBase::GetSortedAnnotationMarks( const SwTextNode& rNode, sal_Int32 nAktPos, sal_Int32 nLen )
+void MSWordExportBase::GetSortedAnnotationMarks( const SwWW8AttrIter& rAttrs, sal_Int32 nAktPos, sal_Int32 nLen )
 {
     IMarkVector aMarksStart;
-    if ( GetAnnotationMarks( rNode, nAktPos, nAktPos + nLen, aMarksStart ) )
+    if ( GetAnnotationMarks( rAttrs, nAktPos, nAktPos + nLen, aMarksStart ) )
     {
         IMarkVector aSortedEnd;
         IMarkVector aSortedStart;
@@ -2113,6 +2138,7 @@ void MSWordExportBase::GetSortedAnnotationMarks( const SwTextNode& rNode, sal_In
             const sal_Int32 nStart = pMark->GetMarkStart().nContent.GetIndex();
             const sal_Int32 nEnd = pMark->GetMarkEnd().nContent.GetIndex();
 
+            const SwTextNode& rNode = rAttrs.GetNode();
             if ( nStart > nAktPos && ( pMark->GetMarkStart().nNode == rNode.GetIndex()) )
                 aSortedStart.push_back( pMark );
 
@@ -2383,7 +2409,7 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
             // Append bookmarks in this range after flys, exclusive of final
             // position of this range
             AppendBookmarks( rNode, nAktPos, nNextAttr - nAktPos );
-            AppendAnnotationMarks( rNode, nAktPos, nNextAttr - nAktPos );
+            AppendAnnotationMarks( aAttrIter, nAktPos, nNextAttr - nAktPos );
 
             // At the moment smarttags are only written for paragraphs, at the
             // beginning of the paragraph.
@@ -2553,7 +2579,7 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
                         nStateOfFlyFrame = aAttrIter.OutFlys( nEnd );
                         // insert final bookmarks if any before CR and after flys
                         AppendBookmarks( rNode, nEnd, 1 );
-                        AppendAnnotationMarks( rNode, nEnd, 1 );
+                        AppendAnnotationMarks(aAttrIter, nEnd, 1);
                         if ( pTOXSect )
                         {
                             m_aCurrentCharPropStarts.pop();
@@ -2607,7 +2633,7 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
                     nStateOfFlyFrame = aAttrIter.OutFlys( nEnd );
                     // insert final bookmarks if any before CR and after flys
                     AppendBookmarks( rNode, nEnd, 1 );
-                    AppendAnnotationMarks( rNode, nEnd, 1 );
+                    AppendAnnotationMarks(aAttrIter, nEnd, 1);
                     WriteCR( pTextNodeInfoInner );
                     // #i120928 - position of the bullet's graphic is at end of doc
                     if (bLastCR && (!bExported))
diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
index 64bf90dfdac5..612dee47e903 100644
--- a/sw/source/filter/ww8/wrtww8.cxx
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -1474,10 +1474,10 @@ void WW8Export::AppendBookmarks( const SwTextNode& rNd, sal_Int32 nAktPos, sal_I
     }
 }
 
-void WW8Export::AppendAnnotationMarks(const SwTextNode& rNode, sal_Int32 nAktPos, sal_Int32 nLen)
+void WW8Export::AppendAnnotationMarks(const SwWW8AttrIter& rAttrs, sal_Int32 nAktPos, sal_Int32 nLen)
 {
     IMarkVector aMarks;
-    if (GetAnnotationMarks(rNode, nAktPos, nAktPos + nLen, aMarks))
+    if (GetAnnotationMarks(rAttrs, nAktPos, nAktPos + nLen, aMarks))
     {
         for (IMarkVector::const_iterator it = aMarks.begin(), end = aMarks.end(); it != end; ++it)
         {
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index c95323f6edfc..755c9fdf39bc 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -679,7 +679,7 @@ public:
 
     virtual void AppendBookmark( const OUString& rName ) = 0;
 
-    virtual void AppendAnnotationMarks( const SwTextNode& rNd, sal_Int32 nAktPos, sal_Int32 nLen ) = 0;
+    virtual void AppendAnnotationMarks( const SwWW8AttrIter& rAttrs, sal_Int32 nAktPos, sal_Int32 nLen ) = 0;
 
     virtual void AppendSmartTags(SwTextNode& /*rTextNode*/) { }
 
@@ -858,9 +858,9 @@ protected:
     ///
     void NearestAnnotationMark( sal_Int32& rNearest, const sal_Int32 nAktPos, bool bNextPositionOnly );
 
-    void GetSortedAnnotationMarks( const SwTextNode& rNd, sal_Int32 nAktPos, sal_Int32 nLen );
+    void GetSortedAnnotationMarks( const SwWW8AttrIter& rAttrs, sal_Int32 nAktPos, sal_Int32 nLen );
 
-    bool GetAnnotationMarks( const SwTextNode& rNd, sal_Int32 nStt, sal_Int32 nEnd,
+    bool GetAnnotationMarks( const SwWW8AttrIter& rAttrs, sal_Int32 nStt, sal_Int32 nEnd,
             IMarkVector& rArr );
 
     const NfKeywordTable & GetNfKeywordTable();
@@ -1047,7 +1047,7 @@ public:
     virtual void AppendBookmark( const OUString& rName ) override;
     void AppendBookmarkEndWithCorrection( const OUString& rName );
 
-    virtual void AppendAnnotationMarks( const SwTextNode& rNd, sal_Int32 nAktPos, sal_Int32 nLen ) override;
+    virtual void AppendAnnotationMarks( const SwWW8AttrIter& rAttrs, sal_Int32 nAktPos, sal_Int32 nLen ) override;
 
     virtual void AppendSmartTags(SwTextNode& rTextNode) override;
 
@@ -1508,6 +1508,7 @@ public:
     const SwRedlineData* GetParagraphLevelRedline( );
     const SwRedlineData* GetRunLevelRedline( sal_Int32 nPos );
     FlyProcessingState OutFlys(sal_Int32 nSwPos);
+    bool HasFlysAt(sal_Int32 nSwPos) const;
 
     sal_Int32 WhereNext() const { return nAktSwPos; }
     sal_uInt16 GetScript() const { return mnScript; }
@@ -1521,6 +1522,8 @@ public:
     bool IsAnchorLinkedToThisNode( sal_uLong nNodePos );
 
     void SplitRun( sal_Int32 nSplitEndPos );
+
+    const SwTextNode& GetNode() const { return rNd; }
 };
 
 /// Class to collect and output the styles table.
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index f17a52da1697..2d328e299e09 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -57,6 +57,7 @@
 #include <com/sun/star/text/XParagraphCursor.hpp>
 #include <com/sun/star/text/XRedline.hpp>
 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
+#include <com/sun/star/text/XTextRangeCompare.hpp>
 #include <com/sun/star/style/DropCapFormat.hpp>
 #include <com/sun/star/util/NumberFormatter.hpp>
 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
@@ -1942,12 +1943,30 @@ void DomainMapper_Impl::PopAnnotation()
             // Create a range that points to the annotation start/end.
             uno::Reference<text::XText> const xText = aAnnotationPosition.m_xStart->getText();
             uno::Reference<text::XTextCursor> const xCursor = xText->createTextCursorByRange(aAnnotationPosition.m_xStart);
+
+            bool bMarker = false;
+            uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xText, uno::UNO_QUERY);
+            if (xTextRangeCompare->compareRegionStarts(aAnnotationPosition.m_xStart, aAnnotationPosition.m_xEnd) == 0)
+            {
+                // Insert a marker so that comment around an anchored image is not collapsed during
+                // insertion.
+                xText->insertString(xCursor, "x", false);
+                bMarker = true;
+            }
+
             xCursor->gotoRange(aAnnotationPosition.m_xEnd, true);
             uno::Reference<text::XTextRange> const xTextRange(xCursor, uno::UNO_QUERY_THROW);
 
             // Attach the annotation to the range.
             uno::Reference<text::XTextAppend> const xTextAppend = m_aTextAppendStack.top().xTextAppend;
             xTextAppend->insertTextContent(xTextRange, uno::Reference<text::XTextContent>(m_xAnnotationField, uno::UNO_QUERY_THROW), !xCursor->isCollapsed());
+
+            if (bMarker)
+            {
+                // Remove the marker.
+                xCursor->goLeft(1, true);
+                xCursor->setString(OUString());
+            }
         }
         m_aAnnotationPositions.erase( m_nAnnotationId );
     }


More information about the Libreoffice-commits mailing list