summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2017-03-02 18:55:50 +0300
committerMiklos Vajna <vmiklos@collabora.co.uk>2017-03-07 09:00:30 +0000
commit7d265e093bc8078471e87da85c625ef2365a1637 (patch)
treefe7fab942aa58ea52f1af1feebac47cecfb7f145 /sw
parentf4e6a22c27ef5ce3ecb046ecd88a1dc0b37c7870 (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. Change-Id: If043cfc466879d45141c655f7be1588792f898d3 Reviewed-on: https://gerrit.libreoffice.org/34820 Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> Tested-by: Mike Kaganski <mike.kaganski@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/34884 Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk> Tested-by: Miklos Vajna <vmiklos@collabora.co.uk>
Diffstat (limited to 'sw')
-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.cxx103
3 files changed, 92 insertions, 20 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 1df4a6c5bbf8..3220a523740a 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 80d5ca7cc81f..f7693b0e761a 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