summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2017-03-02 18:55:50 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2017-03-29 12:49:39 +0000
commit36f2eae1cd9ffe7cee915a72454a8e743cbf9bdd (patch)
tree7b58fd125306141c7705e1631dd435fd15d08e74
parent0a483513f198d2e4bbeb2368d5f0763721f9a062 (diff)
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. Reviewed-on: https://gerrit.libreoffice.org/34820 Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> Tested-by: Mike Kaganski <mike.kaganski@collabora.com> (cherry picked from commit bb2a3df2d5b5a01aa58fb3567686e50762186036) Change-Id: I6c3803635f006dd396805d6847daa4d80c97cad4 Reviewed-on: https://gerrit.libreoffice.org/34863 Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> Tested-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r--sw/qa/extras/ww8import/data/tdf106291.docbin0 -> 24064 bytes
-rw-r--r--sw/qa/extras/ww8import/ww8import.cxx9
-rw-r--r--sw/source/filter/ww8/ww8par2.cxx88
3 files changed, 82 insertions, 15 deletions
diff --git a/sw/qa/extras/ww8import/data/tdf106291.doc b/sw/qa/extras/ww8import/data/tdf106291.doc
new file mode 100644
index 000000000000..893004d46118
--- /dev/null
+++ b/sw/qa/extras/ww8import/data/tdf106291.doc
Binary files differ
diff --git a/sw/qa/extras/ww8import/ww8import.cxx b/sw/qa/extras/ww8import/ww8import.cxx
index bdbf84773212..3727c58d090b 100644
--- a/sw/qa/extras/ww8import/ww8import.cxx
+++ b/sw/qa/extras/ww8import/ww8import.cxx
@@ -56,6 +56,15 @@ DECLARE_WW8IMPORT_TEST(testFloatingTableSectionColumns, "floating-table-section-
CPPUNIT_ASSERT( tableWidth.toInt32() > 10000 );
}
+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
+}
+
// tests should only be added to ww8IMPORT *if* they fail round-tripping in ww8EXPORT
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/ww8/ww8par2.cxx b/sw/source/filter/ww8/ww8par2.cxx
index 146d22693acc..76b7b9dffae0 100644
--- a/sw/source/filter/ww8/ww8par2.cxx
+++ b/sw/source/filter/ww8/ww8par2.cxx
@@ -75,10 +75,12 @@
using namespace ::com::sun::star;
+// Gets filled in WW8TabDesc::MergeCells().
+// Algorithm must ensure proper row and column order in WW8SelBoxInfo!
class WW8SelBoxInfo
{
private:
- std::vector<SwTableBox*> m_vBoxes;
+ std::vector<std::vector<SwTableBox*> > m_vRows;
WW8SelBoxInfo(WW8SelBoxInfo const&) = delete;
WW8SelBoxInfo& operator=(WW8SelBoxInfo const&) = delete;
@@ -92,11 +94,35 @@ public:
: nGroupXStart( nXCenter ), nGroupWidth( nWidth ), bGroupLocked(false)
{}
- size_t size() const { return m_vBoxes.size(); }
+ 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(); }
- SwTableBox* operator[]( size_t nIndex ) { return m_vBoxes[nIndex]; }
+ const std::vector<SwTableBox*>& row( size_t nIndex ) { return m_vRows[nIndex]; }
- void push_back( SwTableBox* pBox ) { m_vBoxes.push_back(pBox); }
+ 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()
@@ -2120,6 +2146,15 @@ void WW8TabDesc::CalcDefaults()
if( pR->nCenter[0] < m_nMinLeft )
m_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++ )
{
/*
@@ -2132,10 +2167,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] > m_nMaxRight )
@@ -2531,7 +2576,8 @@ void WW8TabDesc::MergeCells()
for (m_pActBand=m_pFirstBand, nRow=0; m_pActBand; m_pActBand=m_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( m_pActBand->pTCs )
{
for( short j = 0; j < m_pActBand->nRows; j++, nRow++ )
@@ -2716,18 +2762,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));
+ }
+ }
}
}
}