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

Mike Kaganski mike.kaganski at collabora.com
Tue Mar 7 09:01:23 UTC 2017


 sw/qa/extras/ww8import/data/tdf106291.doc |binary
 sw/qa/extras/ww8import/ww8import.cxx      |    9 ++
 sw/source/filter/ww8/ww8par2.cxx          |  103 ++++++++++++++++++++++++------
 3 files changed, 92 insertions(+), 20 deletions(-)

New commits:
commit 7d265e093bc8078471e87da85c625ef2365a1637
Author: Mike Kaganski <mike.kaganski at collabora.com>
Date:   Thu Mar 2 18:55:50 2017 +0300

    tdf#106291: WW8 import: Properly treat column spans
    
    Previous code unconditionally treated all cells in merge groups as
    rows span, thus in some conditions it merged incorrectly when there
    were cells from same row.
    
    The fix is inspired by SwTable::PrepareMerge().
    
    Also, fixed improper adjustment of too narrow cells in
    WW8TabDesc::CalcDefaults(), which also happens in files where
    column spans are represented by spanned 1-twip-wide cells.
    
    Unit test included.
    
    Change-Id: If043cfc466879d45141c655f7be1588792f898d3
    Reviewed-on: https://gerrit.libreoffice.org/34820
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    Tested-by: Mike Kaganski <mike.kaganski at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/34884
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/sw/qa/extras/ww8import/data/tdf106291.doc b/sw/qa/extras/ww8import/data/tdf106291.doc
new file mode 100644
index 0000000..893004d
Binary files /dev/null and b/sw/qa/extras/ww8import/data/tdf106291.doc differ
diff --git a/sw/qa/extras/ww8import/ww8import.cxx b/sw/qa/extras/ww8import/ww8import.cxx
index 1df4a6c..3220a52 100644
--- a/sw/qa/extras/ww8import/ww8import.cxx
+++ b/sw/qa/extras/ww8import/ww8import.cxx
@@ -553,6 +553,15 @@ DECLARE_WW8IMPORT_TEST(testTdf99120, "tdf99120.doc")
     CPPUNIT_ASSERT_EQUAL(OUString("Section 2, even."),  parseDump("/root/page[4]/header/txt/text()"));
 }
 
+DECLARE_WW8IMPORT_TEST(testTdf106291, "tdf106291.doc")
+{
+    // Table cell was merged vertically instead of horizontally -> had incorrect dimensions
+    OUString cellWidth = parseDump("/root/page[1]/body/tab/row/cell[1]/infos/bounds", "width");
+    OUString cellHeight = parseDump("/root/page[1]/body/tab/row/cell[1]/infos/bounds", "height");
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(8660), cellWidth.toInt32());
+    CPPUNIT_ASSERT(cellHeight.toInt32() > 200); // height might depend on font size
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par2.cxx b/sw/source/filter/ww8/ww8par2.cxx
index 80d5ca7c..f7693b0 100644
--- a/sw/source/filter/ww8/ww8par2.cxx
+++ b/sw/source/filter/ww8/ww8par2.cxx
@@ -75,9 +75,16 @@
 
 using namespace ::com::sun::star;
 
+// Gets filled in WW8TabDesc::MergeCells().
+// Algorithm must ensure proper row and column order in WW8SelBoxInfo!
 class WW8SelBoxInfo
-    : public std::vector<SwTableBox*>, private boost::noncopyable
 {
+private:
+    std::vector<std::vector<SwTableBox*> > m_vRows;
+
+    WW8SelBoxInfo(WW8SelBoxInfo const&) = delete;
+    WW8SelBoxInfo& operator=(WW8SelBoxInfo const&) = delete;
+
 public:
     short nGroupXStart;
     short nGroupWidth;
@@ -86,6 +93,36 @@ public:
     WW8SelBoxInfo(short nXCenter, short nWidth)
         : nGroupXStart( nXCenter ), nGroupWidth( nWidth ), bGroupLocked(false)
     {}
+
+    size_t size() const
+    {
+        size_t nResult = 0;
+        for (auto& it : m_vRows)
+            nResult += it.size();
+        return nResult;
+    }
+
+    size_t rowsCount() const { return m_vRows.size(); }
+
+    const std::vector<SwTableBox*>& row( size_t nIndex ) { return m_vRows[nIndex]; }
+
+    void push_back( SwTableBox* pBox )
+    {
+        bool bDone = false;
+        for (auto& iRow : m_vRows)
+            if (iRow[0]->GetUpper() == pBox->GetUpper())
+            {
+                iRow.push_back(pBox);
+                bDone = true;
+                break;
+            }
+        if (!bDone)
+        {
+            const size_t sz = m_vRows.size();
+            m_vRows.resize(sz+1);
+            m_vRows[sz].push_back(pBox);
+        }
+    }
 };
 
 WW8TabBandDesc::WW8TabBandDesc()
@@ -162,7 +199,7 @@ class WW8TabDesc: private boost::noncopyable
 
     // single box - maybe used in a merge group
     // (the merge groups are processed later at once)
-    SwTableBox* UpdateTableMergeGroup(WW8_TCell& rCell,
+    void UpdateTableMergeGroup(WW8_TCell& rCell,
         WW8SelBoxInfo* pActGroup, SwTableBox* pActBox, sal_uInt16 nCol  );
     void StartMiserableHackForUnsupportedDirection(short nWwCol);
     void EndMiserableHackForUnsupportedDirection(short nWwCol);
@@ -2104,6 +2141,15 @@ void WW8TabDesc::CalcDefaults()
         if( pR->nCenter[0] < nMinLeft )
             nMinLeft = pR->nCenter[0];
 
+        // Following adjustment moves a border and then uses it to find width
+        // of next cell, so collect current widths, to avoid situation when width
+        // adjustment to too narrow cell makes next cell have negative width
+        short nOrigWidth[MAX_COL + 1];
+        for( short i = 0; i < pR->nWwCols; i++ )
+        {
+            nOrigWidth[i] = pR->nCenter[i+1] - pR->nCenter[i];
+        }
+
         for( short i = 0; i < pR->nWwCols; i++ )
         {
            /*
@@ -2116,10 +2162,20 @@ void WW8TabDesc::CalcDefaults()
             #i28333# If the nGapHalf is greater than the cell width best to ignore it
             */
             int nCellWidth = pR->nCenter[i+1] - pR->nCenter[i];
+            if (nCellWidth != nOrigWidth[i])
+            {
+                if (nOrigWidth[i] == 0)
+                    nCellWidth = 0; // restore zero-width "cell"
+                else if ((pR->nGapHalf >= nCellWidth) && (pR->nGapHalf < nOrigWidth[i]))
+                    nCellWidth = pR->nGapHalf + 1; // avoid false ignore
+                else if ((nCellWidth <= 0) && (nOrigWidth[i] > 0))
+                    nCellWidth = 1; // minimal non-zero width to minimize distortion
+            }
             if (nCellWidth && ((nCellWidth - pR->nGapHalf*2) < MINLAY) && pR->nGapHalf < nCellWidth)
             {
-                pR->nCenter[i+1] = pR->nCenter[i]+MINLAY+pR->nGapHalf * 2;
+                nCellWidth = MINLAY + pR->nGapHalf * 2;
             }
+            pR->nCenter[i + 1] = pR->nCenter[i] + nCellWidth;
         }
 
         if( pR->nCenter[pR->nWwCols] > nMaxRight )
@@ -2518,7 +2574,8 @@ void WW8TabDesc::MergeCells()
 
     for (pActBand=pFirstBand, nRow=0; pActBand; pActBand=pActBand->pNextBand)
     {
-        // insert current box into merge group if appropriate
+        // insert current box into merge group if appropriate.
+        // The algorithm must ensure proper row and column order in WW8SelBoxInfo!
         if( pActBand->pTCs )
         {
             for( short j = 0; j < pActBand->nRows; j++, nRow++ )
@@ -2703,18 +2760,30 @@ void WW8TabDesc::FinishSwTable()
         // process all merge groups one by one
         for (auto const& groupIt : m_MergeGroups)
         {
-            sal_uInt16 nActBoxCount = groupIt->size();
-
-            if( ( 1 < nActBoxCount ) && (*groupIt)[0] )
+            if((1 < groupIt->size()) && groupIt->row(0)[0])
             {
-                const sal_uInt16 nRowSpan = groupIt->size();
+                SwFrameFormat* pNewFormat = groupIt->row(0)[0]->ClaimFrameFormat();
+                pNewFormat->SetFormatAttr(SwFormatFrameSize(ATT_VAR_SIZE, groupIt->nGroupWidth, 0));
+                const sal_uInt16 nRowSpan = groupIt->rowsCount();
                 for (sal_uInt16 n = 0; n < nRowSpan; ++n)
                 {
-                    SwTableBox* pCurrentBox = (*groupIt)[n];
-                    const long nRowSpanSet = n == 0 ?
-                                               nRowSpan :
-                                             ((-1) * (nRowSpan - n));
-                    pCurrentBox->setRowSpan( nRowSpanSet );
+                    auto& rRow = groupIt->row(n);
+                    for (size_t i = 0; i<rRow.size(); ++i)
+                    {
+                        const long nRowSpanSet = (n == 0) && (i == 0) ?
+                            nRowSpan :
+                            ((-1) * (nRowSpan - n));
+                        SwTableBox* pCurrentBox = rRow[i];
+                        pCurrentBox->setRowSpan(nRowSpanSet);
+
+                        if (i == 0)
+                            pCurrentBox->ChgFrameFormat(static_cast<SwTableBoxFormat*>(pNewFormat));
+                        else
+                        {
+                            SwFrameFormat* pFormat = pCurrentBox->ClaimFrameFormat();
+                            pFormat->SetFormatAttr(SwFormatFrameSize(ATT_VAR_SIZE, 0, 0));
+                        }
+                    }
                 }
             }
         }
@@ -3257,14 +3326,11 @@ void WW8TabDesc::TableCellEnd()
 }
 
 // if necessary register the box for the merge group for this column
-SwTableBox* WW8TabDesc::UpdateTableMergeGroup(  WW8_TCell&     rCell,
+void WW8TabDesc::UpdateTableMergeGroup(  WW8_TCell&     rCell,
                                                 WW8SelBoxInfo* pActGroup,
                                                 SwTableBox*    pActBox,
                                                 sal_uInt16         nCol )
 {
-    // set default for return
-    SwTableBox* pResult = nullptr;
-
     // check if the box has to be merged
     // If cell is the first one to be merged, a new merge group has to be provided.
     // E.g., it could be that a cell is the first one to be merged, but no
@@ -3291,11 +3357,8 @@ SwTableBox* WW8TabDesc::UpdateTableMergeGroup(  WW8_TCell&     rCell,
         {
             // add current box to merge group
             pTheMergeGroup->push_back(pActBox);
-            // return target box
-            pResult = (*pTheMergeGroup)[ 0 ];
         }
     }
-    return pResult;
 }
 
 sal_uInt16 WW8TabDesc::GetLogicalWWCol() const // returns number of col as INDICATED within WW6 UI status line -1


More information about the Libreoffice-commits mailing list