[Libreoffice-commits] core.git: Branch 'distro/collabora/dcm-6.2' - 21 commits - include/svx svx/source sw/qa sw/source writerfilter/source
Miklos Vajna (via logerrit)
logerrit at kemper.freedesktop.org
Mon Mar 8 10:57:00 UTC 2021
include/svx/framelink.hxx | 7
svx/source/dialog/framelink.cxx | 117 ++++++
sw/qa/extras/ooxmlexport/data/tdf116194.docx |binary
sw/qa/extras/ooxmlexport/data/tdf119054.docx |binary
sw/qa/extras/ooxmlexport/data/tdf124399_SingleCellTableBorders.docx |binary
sw/qa/extras/ooxmlexport/data/tdf127814.docx |binary
sw/qa/extras/ooxmlexport/data/tdf128752.docx |binary
sw/qa/extras/ooxmlexport/data/tdf129442_RightBorder.docx |binary
sw/qa/extras/ooxmlexport/data/tdf129450_BottomBorder.docx |binary
sw/qa/extras/ooxmlexport/data/tdf129452_BottomBorders.docx |binary
sw/qa/extras/ooxmlexport/data/tdf129575-directAfter.docx |binary
sw/qa/extras/ooxmlexport/data/tdf129575-directBefore.docx |binary
sw/qa/extras/ooxmlexport/data/tdf129575-docDefault.docx |binary
sw/qa/extras/ooxmlexport/data/tdf129575-styleAfter.docx |binary
sw/qa/extras/ooxmlexport/data/tdf81100.docx |binary
sw/qa/extras/ooxmlexport/ooxmlexport10.cxx | 11
sw/qa/extras/ooxmlexport/ooxmlexport11.cxx | 20 +
sw/qa/extras/ooxmlexport/ooxmlexport3.cxx | 48 ++
sw/qa/extras/ooxmlexport/ooxmlexport6.cxx | 30 +
sw/qa/extras/ooxmlexport/ooxmlexport8.cxx | 6
sw/qa/extras/ooxmlexport/ooxmlexport9.cxx | 65 +++
sw/qa/extras/rtfimport/rtfimport.cxx | 2
sw/source/core/inc/cellfrm.hxx | 6
sw/source/core/layout/paintfrm.cxx | 76 ++++
sw/source/core/layout/tabfrm.cxx | 84 ++++
sw/source/filter/ww8/docxattributeoutput.cxx | 2
sw/source/filter/ww8/docxtablestyleexport.cxx | 23 +
writerfilter/source/dmapper/ConversionHelper.cxx | 9
writerfilter/source/dmapper/ConversionHelper.hxx | 1
writerfilter/source/dmapper/DomainMapper.cxx | 8
writerfilter/source/dmapper/DomainMapperTableHandler.cxx | 181 +++++++---
writerfilter/source/dmapper/DomainMapperTableHandler.hxx | 3
writerfilter/source/dmapper/DomainMapperTableManager.cxx | 69 +--
writerfilter/source/dmapper/DomainMapperTableManager.hxx | 2
writerfilter/source/dmapper/DomainMapper_Impl.cxx | 89 +++-
writerfilter/source/dmapper/DomainMapper_Impl.hxx | 19 -
writerfilter/source/dmapper/PropertyIds.cxx | 10
writerfilter/source/dmapper/PropertyIds.hxx | 62 +--
writerfilter/source/dmapper/PropertyMap.cxx | 28 +
writerfilter/source/dmapper/PropertyMap.hxx | 19 -
writerfilter/source/dmapper/StyleSheetTable.cxx | 22 -
writerfilter/source/dmapper/StyleSheetTable.hxx | 1
writerfilter/source/dmapper/TableData.hxx | 41 ++
writerfilter/source/dmapper/TableManager.cxx | 76 ++++
writerfilter/source/dmapper/TableManager.hxx | 8
writerfilter/source/dmapper/TblStylePrHandler.cxx | 12
writerfilter/source/ooxml/OOXMLFastContextHandler.cxx | 4
writerfilter/source/ooxml/model.xml | 5
48 files changed, 1002 insertions(+), 164 deletions(-)
New commits:
commit 630e1a35d189d07a9bade63279ad179bbcd7318e
Author: Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Mar 4 11:52:58 2021 +0100
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 17:50:38 2021 +0100
sw: fix unwanted long vertical border around vertically merged Word cell
In case cells A1 and A2 are vertically merged, they can still specify
different border properties for the two cells. Word draws the border
properties of the covered cells, while Writer ignores the formatting of
A2 in this case and only uses the properties of the covering cell.
Table cell border collapsing rules already differ in Word and Writer, so
SwTabFramePainter::Insert() knows if the table cell's border is
Word-style or not. Extend this code to handle vertically merged cells
better.
In general, this means a cell no longer has a fixed set of 4 borders,
but each edge may have several sub-borders. This commit is a step in
that direction, and handles the case when a vertical (left or right)
border style is set initially, but not set at the end -- as we iterate
through the list of cells in a vertical merge.
(cherry picked from commit 66ac8e60896f6306bed8fbb34606fd14474f19ce)
Conflicts:
sw/qa/core/layout/layout.cxx
sw/source/core/layout/paintfrm.cxx
Change-Id: I35a05097ce70243099307ce8066766aef61a2bc5
diff --git a/sw/source/core/inc/cellfrm.hxx b/sw/source/core/inc/cellfrm.hxx
index 4e293a601f45..894763d410ef 100644
--- a/sw/source/core/inc/cellfrm.hxx
+++ b/sw/source/core/inc/cellfrm.hxx
@@ -59,6 +59,12 @@ public:
const SwCellFrame& FindStartEndOfRowSpanCell( bool bStart ) const;
long GetLayoutRowSpan() const;
+ /// If this is a vertically merged cell, then looks up its covered cell in rRow.
+ const SwCellFrame* GetCoveredCellInRow(const SwRowFrame& rRow) const;
+
+ /// If this is a vertically merged cell, then looks up its covered cells.
+ std::vector<const SwCellFrame*> GetCoveredCells() const;
+
void dumpAsXmlAttributes(xmlTextWriterPtr writer) const override;
};
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index fc15487b774c..9d7029f2f19d 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -2213,11 +2213,14 @@ struct SwLineEntry
SwTwips mnKey;
SwTwips mnStartPos;
SwTwips mnEndPos;
+ SwTwips mnLimitedEndPos;
svx::frame::Style maAttribute;
enum OverlapType { NO_OVERLAP, OVERLAP1, OVERLAP2, OVERLAP3 };
+ enum class VerticalType { LEFT, RIGHT };
+
public:
SwLineEntry( SwTwips nKey,
SwTwips nStartPos,
@@ -2225,6 +2228,12 @@ public:
const svx::frame::Style& rAttribute );
OverlapType Overlaps( const SwLineEntry& rComp ) const;
+
+ /**
+ * Assuming that this entry is for a Word-style covering cell and the border matching eType is
+ * set, limit the end position of this border in case covered cells have no borders set.
+ */
+ void LimitVerticalEndPos(const SwFrame& rFrame, VerticalType eType);
};
SwLineEntry::SwLineEntry( SwTwips nKey,
@@ -2234,6 +2243,7 @@ SwLineEntry::SwLineEntry( SwTwips nKey,
: mnKey( nKey ),
mnStartPos( nStartPos ),
mnEndPos( nEndPos ),
+ mnLimitedEndPos(0),
maAttribute( rAttribute )
{
}
@@ -2287,6 +2297,37 @@ SwLineEntry::OverlapType SwLineEntry::Overlaps( const SwLineEntry& rNew ) const
return eRet;
}
+void SwLineEntry::LimitVerticalEndPos(const SwFrame& rFrame, VerticalType eType)
+{
+ if (!rFrame.IsCellFrame())
+ {
+ return;
+ }
+
+ const auto& rCellFrame = static_cast<const SwCellFrame&>(rFrame);
+ std::vector<const SwCellFrame*> aCoveredCells = rCellFrame.GetCoveredCells();
+ // Iterate in reverse order, so we can stop at the first cell that has a border. This can
+ // determine what is the minimal end position that is safe to use as a limit.
+ for (auto it = aCoveredCells.rbegin(); it != aCoveredCells.rend(); ++it)
+ {
+ const SwCellFrame* pCoveredCell = *it;
+ SwBorderAttrAccess aAccess( SwFrame::GetCache(), pCoveredCell );
+ const SwBorderAttrs& rAttrs = *aAccess.Get();
+ const SvxBoxItem& rBox = rAttrs.GetBox();
+ if (eType == VerticalType::LEFT && rBox.GetLeft())
+ {
+ break;
+ }
+
+ if (eType == VerticalType::RIGHT && rBox.GetRight())
+ {
+ break;
+ }
+
+ mnLimitedEndPos = pCoveredCell->getFrameArea().Top();
+ }
+}
+
struct lt_SwLineEntry
{
bool operator()( const SwLineEntry& e1, const SwLineEntry& e2 ) const
@@ -2422,6 +2463,12 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
svx::frame::Style aStyles[ 7 ];
aStyles[ 0 ] = rEntryStyle;
FindStylesForLine( aStart, aEnd, aStyles, bHori );
+
+ if (!bHori && rEntry.mnLimitedEndPos)
+ {
+ aEnd.setY(rEntry.mnLimitedEndPos);
+ }
+
SwRect aRepaintRect( aStart, aEnd );
// the repaint rectangle has to be moved a bit for the centered lines:
@@ -2741,8 +2788,17 @@ void SwTabFramePainter::Insert(const SwFrame& rFrame, const SvxBoxItem& rBoxItem
SwLineEntry aLeft (nLeft, nTop, nBottom,
bVert ? aB : (bR2L ? aR : aL));
+ if (bWordTableCell && rBoxItem.GetLeft())
+ {
+ aLeft.LimitVerticalEndPos(rFrame, SwLineEntry::VerticalType::LEFT);
+ }
+
SwLineEntry aRight (nRight, nTop, nBottom,
bVert ? (bBottomAsTop ? aB : aT) : (bR2L ? aL : aR));
+ if (bWordTableCell && rBoxItem.GetRight())
+ {
+ aRight.LimitVerticalEndPos(rFrame, SwLineEntry::VerticalType::RIGHT);
+ }
SwLineEntry aTop (nTop, nLeft, nRight,
bVert ? aL : (bBottomAsTop ? aB : aT));
SwLineEntry aBottom(nBottom, nLeft, nRight,
@@ -2773,6 +2829,14 @@ void SwTabFramePainter::Insert( SwLineEntry& rNew, bool bHori )
while ( aIter != pLineSet->end() && rNew.mnStartPos < rNew.mnEndPos )
{
const SwLineEntry& rOld = *aIter;
+
+ if (rOld.mnLimitedEndPos)
+ {
+ // Don't merge with this line entry as it ends sooner than mnEndPos.
+ ++aIter;
+ continue;
+ }
+
const SwLineEntry::OverlapType nOverlapType = rOld.Overlaps( rNew );
const svx::frame::Style& rOldAttr = rOld.maAttribute;
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index a379e71dbaed..eeb2ab36658b 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -5296,6 +5296,90 @@ long SwCellFrame::GetLayoutRowSpan() const
return nRet;
}
+const SwCellFrame* SwCellFrame::GetCoveredCellInRow(const SwRowFrame& rRow) const
+{
+ if (GetLayoutRowSpan() <= 1)
+ {
+ // Not merged vertically.
+ return nullptr;
+ }
+
+ for (const SwFrame* pCell = rRow.GetLower(); pCell; pCell = pCell->GetNext())
+ {
+ if (!pCell->IsCellFrame())
+ {
+ continue;
+ }
+
+ auto pCellFrame = static_cast<const SwCellFrame*>(pCell);
+ if (!pCellFrame->IsCoveredCell())
+ {
+ continue;
+ }
+
+ if (pCellFrame->getFrameArea().Left() != getFrameArea().Left())
+ {
+ continue;
+ }
+
+ if (pCellFrame->getFrameArea().Width() != getFrameArea().Width())
+ {
+ continue;
+ }
+
+ // pCellFrame is covered, there are only covered cell frames between "this" and pCellFrame
+ // and the horizontal position/size matches "this".
+ return pCellFrame;
+ }
+
+ return nullptr;
+}
+
+std::vector<const SwCellFrame*> SwCellFrame::GetCoveredCells() const
+{
+ std::vector<const SwCellFrame*> aRet;
+ if (GetLayoutRowSpan() <= 1)
+ {
+ return aRet;
+ }
+
+ if (!GetUpper()->IsRowFrame())
+ {
+ return aRet;
+ }
+
+ auto pFirstRowFrame = static_cast<const SwRowFrame*>(GetUpper());
+ if (!pFirstRowFrame->GetNext())
+ {
+ return aRet;
+ }
+
+ if (!pFirstRowFrame->GetNext()->IsRowFrame())
+ {
+ return aRet;
+ }
+
+ for (const SwFrame* pRow = pFirstRowFrame->GetNext(); pRow; pRow = pRow->GetNext())
+ {
+ if (!pRow->IsRowFrame())
+ {
+ continue;
+ }
+
+ auto pRowFrame = static_cast<const SwRowFrame*>(pRow);
+ const SwCellFrame* pCovered = GetCoveredCellInRow(*pRowFrame);
+ if (!pCovered)
+ {
+ continue;
+ }
+
+ // Found a cell in a next row that is covered by "this".
+ aRet.push_back(pCovered);
+ }
+
+ return aRet;
+}
+
void SwCellFrame::dumpAsXmlAttributes(xmlTextWriterPtr pWriter) const
{
SwFrame::dumpAsXmlAttributes(pWriter);
commit 315508bf28a4b58b431ffa5899e9ae23cbab9eca
Author: Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Wed Feb 19 18:03:59 2020 +0100
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 13:25:02 2021 +0100
sw table cell borders: add optional Word-compatible border collapsing
We always compared border width and other aspects only after that, Word
works with border weight according to their implementer notes.
So extend svx::frame::Style to be able to collapse borders using weights
and opt in for that from sw/ in case a compat mode (which is related to
tables, off by default and is set by the DOC/DOCX import) is set.
(cherry picked from commit e6fa52c2c371c7adc9c2c2cb18c3a8cf782cfa4b)
Conflicts:
sw/qa/core/layout/layout.cxx
Change-Id: I1f682789302c88a0d326c6c0263ad3007441cb24
diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index fa629fc24ad2..cab0b59e371d 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -123,6 +123,7 @@ private:
double mfSecn; /// Width of secondary (right or bottom) line.
double mfPatternScale; /// Scale used for line pattern spacing.
SvxBorderLineStyle mnType;
+ bool mbWordTableCell;
public:
/** Constructs an invisible frame style. */
@@ -136,7 +137,8 @@ private:
mfDist(0.0),
mfSecn(0.0),
mfPatternScale(1.0),
- mnType(SvxBorderLineStyle::SOLID)
+ mnType(SvxBorderLineStyle::SOLID),
+ mbWordTableCell(false)
{}
};
@@ -194,6 +196,9 @@ public:
/** Mirrors this style (exchanges primary and secondary), if it is a double frame style. */
Style& MirrorSelf();
+ /** Enables the Word-compatible Style comparison code. */
+ void SetWordTableCell(bool bWordTableCell);
+
bool operator==( const Style& rOther) const;
bool operator<( const Style& rOther) const;
};
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index b4548c6ebed9..c8696b063e0b 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -267,6 +267,16 @@ Style& Style::MirrorSelf()
return *this;
}
+void Style::SetWordTableCell(bool bWordTableCell)
+{
+ if (!maImplStyle)
+ {
+ implEnsureImplStyle();
+ }
+
+ maImplStyle->mbWordTableCell = bWordTableCell;
+}
+
bool Style::operator==( const Style& rOther) const
{
if(!maImplStyle && !rOther.maImplStyle)
@@ -290,6 +300,101 @@ bool Style::operator==( const Style& rOther) const
&& Type() == rOther.Type());
}
+namespace
+{
+/**
+ * Gets the weight of rStyle, according to [MS-OI29500] v20171130, 2.1.168 Part 1 Section 17.4.66,
+ * tcBorders (Table Cell Borders).
+ */
+double GetWordTableCellBorderWeight(const Style& rStyle)
+{
+ double fWidth = rStyle.GetWidth();
+ int nBorderNumber = 0;
+
+ // See lcl_convertBorderStyleFromToken() in writerfilter/ and ConvertBorderStyleFromWord() in
+ // editeng/, this is the opposite of the combination of those functions.
+ switch (rStyle.Type())
+ {
+ case SvxBorderLineStyle::NONE:
+ return 0.0;
+ case SvxBorderLineStyle::DOTTED:
+ case SvxBorderLineStyle::DASHED:
+ return 1.0;
+ case SvxBorderLineStyle::SOLID:
+ // single = 1
+ // thick = 2
+ // wave = 20
+ nBorderNumber = 1;
+ break;
+ case SvxBorderLineStyle::DOUBLE:
+ case SvxBorderLineStyle::DOUBLE_THIN:
+ // double = 3
+ // triple = 10
+ // doubleWave = 21
+ // dashDotStroked = 23
+ nBorderNumber = 3;
+ break;
+ case SvxBorderLineStyle::DASH_DOT:
+ // dotDash = 8
+ nBorderNumber = 8;
+ break;
+ case SvxBorderLineStyle::DASH_DOT_DOT:
+ // dotDotDash = 9
+ nBorderNumber = 9;
+ break;
+ case SvxBorderLineStyle::THINTHICK_SMALLGAP:
+ // thinThickSmallGap = 11
+ nBorderNumber = 11;
+ break;
+ case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
+ // thickThinSmallGap = 12
+ // thinThickThinSmallGap = 13
+ nBorderNumber = 12;
+ break;
+ case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
+ // thinThickMediumGap = 14
+ nBorderNumber = 14;
+ break;
+ case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
+ // thickThinMediumGap = 15
+ // thinThickThinMediumGap = 16
+ nBorderNumber = 15;
+ break;
+ case SvxBorderLineStyle::THINTHICK_LARGEGAP:
+ // thinThickLargeGap = 17
+ nBorderNumber = 17;
+ break;
+ case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
+ // thickThinLargeGap = 18
+ // thinThickThinLargeGap = 19
+ nBorderNumber = 18;
+ break;
+ case SvxBorderLineStyle::FINE_DASHED:
+ // dashSmallGap = 22
+ nBorderNumber = 22;
+ break;
+ case SvxBorderLineStyle::EMBOSSED:
+ // threeDEmboss = 24
+ nBorderNumber = 24;
+ break;
+ case SvxBorderLineStyle::ENGRAVED:
+ // threeDEngrave = 25
+ nBorderNumber = 25;
+ break;
+ case SvxBorderLineStyle::OUTSET:
+ // outset = 26
+ nBorderNumber = 25;
+ break;
+ case SvxBorderLineStyle::INSET:
+ // inset = 27
+ nBorderNumber = 27;
+ break;
+ }
+
+ return nBorderNumber * fWidth;
+}
+}
+
bool Style::operator<( const Style& rOther) const
{
if(!maImplStyle && !rOther.maImplStyle)
@@ -298,6 +403,18 @@ bool Style::operator<( const Style& rOther) const
return false;
}
+ if (maImplStyle && maImplStyle->mbWordTableCell)
+ {
+ // The below code would first compare based on the border width, Word compares based on its
+ // calculated weight, do that in the compat case.
+ double fLW = GetWordTableCellBorderWeight(*this);
+ double fRW = GetWordTableCellBorderWeight(rOther);
+ if (!rtl::math::approxEqual(fLW, fRW))
+ {
+ return fLW < fRW;
+ }
+ }
+
// different total widths -> this<rOther, if this is thinner
double nLW = GetWidth();
double nRW = rOther.GetWidth();
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index de14fa4348ae..fc15487b774c 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -2708,11 +2708,23 @@ void SwTabFramePainter::Insert(const SwFrame& rFrame, const SvxBoxItem& rBoxItem
bool const bVert = mrTabFrame.IsVertical();
bool const bR2L = mrTabFrame.IsRightToLeft();
+ bool bWordTableCell = false;
+ SwViewShell* pShell = rFrame.getRootFrame()->GetCurrShell();
+ if (pShell)
+ {
+ const IDocumentSettingAccess& rIDSA = pShell->GetDoc()->getIDocumentSettingAccess();
+ bWordTableCell = rIDSA.get(DocumentSettingId::TABLE_ROW_KEEP);
+ }
+
// no scaling needed, it's all in the primitives and the target device
svx::frame::Style aL(rBoxItem.GetLeft(), 1.0);
+ aL.SetWordTableCell(bWordTableCell);
svx::frame::Style aR(rBoxItem.GetRight(), 1.0);
+ aR.SetWordTableCell(bWordTableCell);
svx::frame::Style aT(rBoxItem.GetTop(), 1.0);
+ aT.SetWordTableCell(bWordTableCell);
svx::frame::Style aB(rBoxItem.GetBottom(), 1.0);
+ aB.SetWordTableCell(bWordTableCell);
aR.MirrorSelf();
aB.MirrorSelf();
commit 8f3305936c8c852f36cb7abb2f29f9b6631c032b
Author: Justin Luth <justin.luth at collabora.com>
AuthorDate: Thu Jun 4 18:46:23 2020 +0300
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 11:36:46 2021 +0100
tdf#132898 writerfilter: use last merged cell's bottom border
Previously, this was just using the border set on the first
cell. Obviously, the bottom merged cell should contain the
definitive setting for the bottom border.
This depends on all of the commits for tdf#129452.
P.S. The top border is obviously fine defined by the top merged cell.
P.S. The left/right borders are a bit more interesting.
In MSO, each row's value applies to that section of the
merged cell. I.E., it isn't treated as a cell border at all.
Only noted as a comment here, since how to deal with it
is probably best left as is - defined by the top cell.
(cherry picked from commit 03803de58bd426eb0b726437dc205d92383e8e2e)
Conflicts:
sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
writerfilter/source/dmapper/DomainMapperTableHandler.cxx
Change-Id: Ibe8d31cba5122078ce73020f7816bff0b2ae36c6
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index c0facb42b3dc..4cb518eb29d8 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -850,16 +850,28 @@ CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(Tabl
if ( bMergedVertically )
{
const sal_uInt32 nColumn = m_rDMapper_Impl.getTableManager().findColumn(nRow, nCell);
+ sal_Int32 nLastMergedRow = 0;
for (size_t i = nRow + 1; bMergedVertically && i < m_aCellProperties.size(); i++)
{
const sal_uInt32 nColumnCell = m_rDMapper_Impl.getTableManager().findColumnCell(i, nColumn);
if ( m_aCellProperties[i].size() > sal::static_int_cast<std::size_t>(nColumnCell) )
{
bMergedVertically = bool(m_aCellProperties[i][nColumnCell]->getProperty(PROP_VERTICAL_MERGE));
+ if ( bMergedVertically )
+ nLastMergedRow = i;
}
else
bMergedVertically = false;
}
+
+ // Only consider the bottom border setting from the last merged cell.
+ // Note: in MSO, left/right apply per-unmerged-row. Can't do that in LO, so just using the top cell's borders should be fine.
+ if ( nRow < nLastMergedRow )
+ {
+ (*aCellIterator)->Erase(PROP_BOTTOM_BORDER);
+ const sal_uInt32 nColumnCell = m_rDMapper_Impl.getTableManager().findColumnCell(nLastMergedRow, nColumn);
+ lcl_mergeBorder( PROP_BOTTOM_BORDER, m_aCellProperties[nLastMergedRow][nColumnCell], *aCellIterator );
+ }
}
lcl_computeCellBorders( rInfo.pTableBorders, *aCellIterator, nCell, nRow, bIsEndCol, bIsEndRow, bMergedVertically );
commit 323d1b7eb2137df1dd95882a5c37799b8936dde8
Author: Justin Luth <justin.luth at collabora.com>
AuthorDate: Mon Jun 29 16:47:24 2020 +0300
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 11:31:58 2021 +0100
tdf#129452 writerfilter: use column, not cell when comparing rows
A natural mistake - especially when there are no existing
functions - is to assume that cell number defines column
number, and so it is valid to compare between rows.
This patch provides the functions, and switches this bug's
earlier patch to properly use columns instead of cells.
This commit depends on two prior patches in bug 129452:
Change-Id: Ie305477f0e3468a4a923095d76f520d97fe99ffe
Change-Id: Ibfdac336bbb1f7303c7e585a85c94be37ad6f916
I hope that this implementation covers all the bases.
This code is dreadful to understand,
as witnessed by comments from those much smarter than I.
P.S. I also cancelled a vertical merge if the cell
is not there (in a gridAfter situation).
If a row is shorter than the previous ones,
then a vertically merged cell should not be considered
to be able to span that gap. If the cells below are still
merged, it would be considered a new merged cell.
(cherry picked from commit 19d7f9624e92422409ed2744091d502fdae8692b)
Conflicts:
sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
writerfilter/source/dmapper/DomainMapperTableHandler.cxx
writerfilter/source/dmapper/TableManager.cxx
Change-Id: I63158ac73b1bf86d9f75dd3c1299d1b1a3f08064
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index 1391e47127bd..c0facb42b3dc 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -709,6 +709,9 @@ CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(Tabl
}
}
+ // Note that this is intentionally called "cell" and not "column".
+ // Don't make the mistake that all cell x's will be in the same column.
+ // Merged cells (grid span) in a row will affect the actual column. (fake cells were added to handle gridBefore)
sal_Int32 nCell = 0;
pCellProperties[nRow].realloc( aRowOfCellsIterator->size() );
beans::PropertyValues* pSingleCellProperties = pCellProperties[nRow].getArray();
@@ -844,10 +847,20 @@ CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(Tabl
// tdf#129452 Checking if current cell is vertically merged with all the other cells below to the bottom.
// This must be done in order to apply the bottom border of the table to the first cell in a vertical merge.
bool bMergedVertically = bool(m_aCellProperties[nRow][nCell]->getProperty(PROP_VERTICAL_MERGE));
-
- for (size_t i = nRow + 1; bMergedVertically && i < m_aCellProperties.size(); i++)
- if ( m_aCellProperties[i].size() > sal::static_int_cast<std::size_t>(nCell) )
- bMergedVertically = bool(m_aCellProperties[i][nCell]->getProperty(PROP_VERTICAL_MERGE));
+ if ( bMergedVertically )
+ {
+ const sal_uInt32 nColumn = m_rDMapper_Impl.getTableManager().findColumn(nRow, nCell);
+ for (size_t i = nRow + 1; bMergedVertically && i < m_aCellProperties.size(); i++)
+ {
+ const sal_uInt32 nColumnCell = m_rDMapper_Impl.getTableManager().findColumnCell(i, nColumn);
+ if ( m_aCellProperties[i].size() > sal::static_int_cast<std::size_t>(nColumnCell) )
+ {
+ bMergedVertically = bool(m_aCellProperties[i][nColumnCell]->getProperty(PROP_VERTICAL_MERGE));
+ }
+ else
+ bMergedVertically = false;
+ }
+ }
lcl_computeCellBorders( rInfo.pTableBorders, *aCellIterator, nCell, nRow, bIsEndCol, bIsEndRow, bMergedVertically );
diff --git a/writerfilter/source/dmapper/TableManager.cxx b/writerfilter/source/dmapper/TableManager.cxx
index dd950c3c9d9b..ea18174ea5ce 100644
--- a/writerfilter/source/dmapper/TableManager.cxx
+++ b/writerfilter/source/dmapper/TableManager.cxx
@@ -78,6 +78,40 @@ void TableManager::setCurrentGridSpan(sal_uInt32 nGridSpan)
mTableDataStack.top()->getCurrentRow()->setCurrentGridSpan(nGridSpan);
}
+sal_uInt32 TableManager::findColumn(const sal_uInt32 nRow, const sal_uInt32 nCell)
+{
+ RowData::Pointer_t pRow = mTableDataStack.top()->getRow(nRow);
+ if (!pRow || nCell < pRow->getGridBefore() || nCell >= pRow->getCellCount())
+ return SAL_MAX_UINT32;
+
+ // The gridSpans provide a one-based index, so add up all the spans of the PREVIOUS columns,
+ // and that result will provide the first possible zero-based number for the desired column.
+ sal_uInt32 nColumn = 0;
+ for (sal_uInt32 n = 0; n < nCell; ++n)
+ nColumn += pRow->getGridSpan(n);
+ return nColumn;
+}
+
+sal_uInt32 TableManager::findColumnCell(const sal_uInt32 nRow, const sal_uInt32 nCol)
+{
+ RowData::Pointer_t pRow = mTableDataStack.top()->getRow(nRow);
+ if (!pRow || nCol < pRow->getGridBefore())
+ return SAL_MAX_UINT32;
+
+ sal_uInt32 nCell = 0;
+ sal_uInt32 nGrids = 0;
+ // The gridSpans give us a one-based index, but requested column is zero-based - so keep that in mind.
+ for (const auto& rSpan : pRow->getGridSpans())
+ {
+ nGrids += rSpan;
+ if (nCol < nGrids)
+ return nCell;
+
+ ++nCell;
+ }
+ return SAL_MAX_UINT32; // must be in gridAfter or invalid column request
+}
+
void TableManager::endOfCellAction()
{
}
diff --git a/writerfilter/source/dmapper/TableManager.hxx b/writerfilter/source/dmapper/TableManager.hxx
index f57a23a57f4a..98ac4fbe32bb 100644
--- a/writerfilter/source/dmapper/TableManager.hxx
+++ b/writerfilter/source/dmapper/TableManager.hxx
@@ -469,6 +469,10 @@ public:
void setCurrentGridBefore( sal_uInt32 nSkipGrids );
std::vector<sal_uInt32> getCurrentGridSpans();
void setCurrentGridSpan( sal_uInt32 nGridSpan );
+ /// Given a zero-based row/cell, return the zero-based grid it belongs to, or SAL_MAX_UINT16 for invalid.
+ sal_uInt32 findColumn( const sal_uInt32 nRow, const sal_uInt32 nCell );
+ /// Given a zero-based row/col, return the zero-based cell describing that grid, or SAL_MAX_UINT16 for invalid.
+ sal_uInt32 findColumnCell( const sal_uInt32 nRow, const sal_uInt32 nCol );
void setTableStartsAtCellStart(bool bTableStartsAtCellStart);
void setCellLastParaAfterAutospacing(bool bIsAfterAutospacing);
commit b743f95b8d3b406da3d9b8c9ad017411f1351ad2
Author: László Németh <nemeth at numbertext.org>
AuthorDate: Tue Feb 4 19:31:41 2020 +0100
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 11:04:35 2021 +0100
tdf#129575 DOCX import: fix table style preference
handling by recognizing docDefault properties
instead of default-value based heuristics.
(cherry picked from commit f15d67442972c5f69c71925a6bfa5aa1a39d54eb)
Conflicts:
sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
writerfilter/source/dmapper/PropertyIds.cxx
writerfilter/source/dmapper/PropertyMap.cxx
writerfilter/source/dmapper/PropertyMap.hxx
writerfilter/source/dmapper/StyleSheetTable.cxx
writerfilter/source/dmapper/StyleSheetTable.hxx
Change-Id: I3bab9d85d77d0e5f1c357121b1caf02cbe4899c4
diff --git a/sw/qa/extras/ooxmlexport/data/tdf129575-directAfter.docx b/sw/qa/extras/ooxmlexport/data/tdf129575-directAfter.docx
new file mode 100644
index 000000000000..c9856b02857b
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf129575-directAfter.docx differ
diff --git a/sw/qa/extras/ooxmlexport/data/tdf129575-directBefore.docx b/sw/qa/extras/ooxmlexport/data/tdf129575-directBefore.docx
new file mode 100644
index 000000000000..5e75ef1be5d2
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf129575-directBefore.docx differ
diff --git a/sw/qa/extras/ooxmlexport/data/tdf129575-docDefault.docx b/sw/qa/extras/ooxmlexport/data/tdf129575-docDefault.docx
new file mode 100644
index 000000000000..d7cdf2ec4308
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf129575-docDefault.docx differ
diff --git a/sw/qa/extras/ooxmlexport/data/tdf129575-styleAfter.docx b/sw/qa/extras/ooxmlexport/data/tdf129575-styleAfter.docx
new file mode 100644
index 000000000000..97439011ff55
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf129575-styleAfter.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
index cd1665489db5..4eae1b2a33df 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
@@ -465,9 +465,9 @@ DECLARE_OOXMLEXPORT_TEST(testTdf119054, "tdf119054.docx")
xmlDocPtr pXmlDoc = parseExport();
if (!pXmlDoc)
return;
- // Don't overwrite before and after spacing of Heading2 by table style
- assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "before");
- assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "after");
+ // Overwrite applied table style with before and after spacing of Heading2
+ assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "before", "0");
+ assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "after", "360");
// Use table style based single line spacing instead of the docDefaults' 254
assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "line", "240");
}
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
index e396ac0bea0b..9d6642a153ec 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
@@ -31,6 +31,7 @@
#include <com/sun/star/view/XSelectionSupplier.hpp>
#include <com/sun/star/style/LineSpacing.hpp>
#include <com/sun/star/style/LineSpacingMode.hpp>
+//#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/style/ParagraphAdjust.hpp>
#include <com/sun/star/drawing/XControlShape.hpp>
#include <com/sun/star/text/TextContentAnchorType.hpp>
@@ -159,6 +160,70 @@ DECLARE_OOXMLEXPORT_TEST(testTdf106690Cell, "tdf106690-cell.docx")
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(494), getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), "ParaBottomMargin"));
}
+DECLARE_OOXMLEXPORT_TEST(testTdf129575_directBefore, "tdf129575-directBefore.docx")
+{
+ uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
+ uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), uno::UNO_QUERY);
+ // direct paragraph formatting
+ // This was 212 twips from the table style, but always direct paragraph formatting wins, in the case of the default 0 margin, too
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaTopMargin"));
+ // default margin
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaBottomMargin"));
+}
+
+DECLARE_OOXMLEXPORT_TEST(testTdf129575_directAfter, "tdf129575-directAfter.docx")
+{
+ uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
+ uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), uno::UNO_QUERY);
+ // from table style
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(212), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaTopMargin"));
+ // direct paragraph formatting
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaBottomMargin"));
+}
+
+DECLARE_OOXMLEXPORT_TEST(testTdf129575_styleAfter, "tdf129575-styleAfter.docx")
+{
+ uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
+ uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), uno::UNO_QUERY);
+ // direct paragraph formatting
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaTopMargin"));
+ // from table style
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(212), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaBottomMargin"));
+}
+
+DECLARE_OOXMLEXPORT_TEST(testTdf129575_docDefault, "tdf129575-docDefault.docx")
+{
+ uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
+ uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), uno::UNO_QUERY);
+ // docDefault defines both bottom margin and line spacing, but
+ // applied bottom margin values are based on non-docDefault paragraph styles, line spacing is based on table style
+
+ // docDefault: <w:spacing w:after="160" w:line="320" w:lineRule="auto"/>
+ // table style: <w:spacing w:after="0" w:line="240" w:lineRule="auto"/> (single line space, overwriting bigger docDefault)
+
+ // Paragraph style Normal: <w:spacing w:after="160"/> (same as docDefault),
+ // table style based single line spacing
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(282), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaBottomMargin"));
+ style::LineSpacing aLineSpacing = getProperty<style::LineSpacing>(getParagraphOfText(1, xCell->getText()), "ParaLineSpacing");
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(style::LineSpacingMode::PROP), aLineSpacing.Mode);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(100), aLineSpacing.Height);
+ // Heading 2: <w:spacing w:after="360"/> (different from docDefault),
+ // table style based single line spacing
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(635), getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), "ParaBottomMargin"));
+ aLineSpacing = getProperty<style::LineSpacing>(getParagraphOfText(1, xCell->getText()), "ParaLineSpacing");
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(style::LineSpacingMode::PROP), aLineSpacing.Mode);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(100), aLineSpacing.Height);
+
+}
+
DECLARE_OOXMLEXPORT_TEST(testTdf106970, "tdf106970.docx")
{
// The second paragraph (first numbered one) had 0 bottom margin:
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index a0b077282885..1391e47127bd 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -61,6 +61,7 @@ using namespace ::std;
#define CNF_FIRST_ROW_FIRST_COLUMN 0x004
#define CNF_LAST_ROW_LAST_COLUMN 0x002
#define CNF_LAST_ROW_FIRST_COLUMN 0x001
+#define CNF_ALL 0xFFF
DomainMapperTableHandler::DomainMapperTableHandler(
css::uno::Reference<css::text::XTextAppendAndConvert> const& xText,
@@ -226,6 +227,7 @@ struct TableInfo
PropertyMapPtr pTableBorders;
TableStyleSheetEntry* pTableStyle;
css::beans::PropertyValues aTableProperties;
+ std::vector< PropertyIds > aTablePropertyIds;
TableInfo()
: nLeftBorderDistance(DEF_BORDER_DIST)
@@ -636,6 +638,7 @@ TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo
}
rInfo.aTableProperties = m_aTableProperties->GetPropertyValues();
+ rInfo.aTablePropertyIds = m_aTableProperties->GetPropertyIds();
#ifdef DEBUG_WRITERFILTER
TagLogger::getInstance().startElement("debug.tableprops");
@@ -810,9 +813,6 @@ CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(Tabl
// Remove properties from style/row that aren't allowed in cells
pAllCellProps->Erase( PROP_HEADER_ROW_COUNT );
pAllCellProps->Erase( PROP_TBL_HEADER );
- // Remove paragraph properties from style/row that paragraph style can overwrite
- pAllCellProps->Erase( PROP_PARA_BOTTOM_MARGIN );
- pAllCellProps->Erase( PROP_PARA_LINE_SPACING );
// Then add the cell properties
pAllCellProps->InsertProps(*aCellIterator);
@@ -1018,29 +1018,59 @@ css::uno::Sequence<css::beans::PropertyValues> DomainMapperTableHandler::endTabl
// table style has got bigger precedence than docDefault style,
// but lower precedence than the paragraph styles and direct paragraph formatting
-void DomainMapperTableHandler::ApplyParaProperty(css::beans::PropertyValues aTableProperties, PropertyIds eId)
+void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableInfo & rInfo)
{
- OUString sPropertyName = getPropertyName(eId);
- auto pTableProp = std::find_if(aTableProperties.begin(), aTableProperties.end(),
- [&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; });
- if (pTableProp != aTableProperties.end())
+ for( auto const& eId : rInfo.aTablePropertyIds )
{
- uno::Any aValue = pTableProp->Value;
- for (const auto& rParaProp : m_rDMapper_Impl.m_aParagraphsToEndTable)
+ // apply paragraph and character properties of the table style on table paragraphs
+ if ( isParagraphProperty(eId) || isCharacterProperty(eId) )
{
- // there is no direct paragraph formatting
- if (!rParaProp.m_pPropertyMap->isSet(eId))
+ // check all paragraphs of the table
+ for (const auto& rParaProp : m_rDMapper_Impl.m_aParagraphsToEndTable)
{
- OUString sParaStyleName;
- rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName;
- StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName);
- uno::Any aMargin = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true);
- uno::Any aMarginDocDefault = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, nullptr, true, true);
- // use table style only when 1) both values are empty (no docDefault and paragraph style definitions) or
- // 2) both non-empty values are equal (docDefault paragraph properties are copied to the base paragraph style during import)
- // TODO check the case, when two parent styles modify the docDefault and the last one set back the docDefault value
- if (aMargin == aMarginDocDefault)
- rParaProp.m_rPropertySet->setPropertyValue(sPropertyName, aValue);
+ // there is no direct paragraph formatting
+ if (!rParaProp.m_pPropertyMap->isSet(eId))
+ {
+ bool bDocDefault;
+ OUString sParaStyleName;
+ rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName;
+ StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName);
+ uno::Any aParaStyle = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true, &bDocDefault);
+ // use table style when a docDefault value is applied instead of it,
+ // and there is no associated TableStyleSheetEntry
+ // TODO: replace CNF_ALL with the actual mask
+ if ( (aParaStyle == uno::Any() || bDocDefault) && !rInfo.pTableStyle->GetProperties(CNF_ALL)->getProperty(eId) )
+ {
+ OUString sPropertyName = getPropertyName(eId);
+ auto pTableProp = std::find_if(rInfo.aTableProperties.begin(), rInfo.aTableProperties.end(),
+ [&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; });
+ if (pTableProp != rInfo.aTableProperties.end())
+ {
+ try
+ {
+ rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, pTableProp->Value );
+ }
+ catch ( const uno::Exception & )
+ {
+ SAL_WARN("writerfilter.dmapper", "Exception during table style correction");
+ }
+ }
+ }
+ // table style can overwrite paragraph style, when the paragraph style property has a default value, restore it
+ // TODO remove the associated TableStyleSheetEntry styles, if needed
+ else if ( aParaStyle != uno::Any() && !bDocDefault )
+ {
+ OUString sPropertyName = getPropertyName(eId);
+ try
+ {
+ rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, aParaStyle );
+ }
+ catch ( const uno::Exception & )
+ {
+ SAL_WARN("writerfilter.dmapper", "Exception during table style correction");
+ }
+ }
+ }
}
}
}
@@ -1144,9 +1174,8 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
}
}
- // OOXML table style may container paragraph properties, apply these now.
- ApplyParaProperty(aTableInfo.aTableProperties, PROP_PARA_BOTTOM_MARGIN);
- ApplyParaProperty(aTableInfo.aTableProperties, PROP_PARA_LINE_SPACING);
+ // OOXML table style may contain paragraph properties, apply these now.
+ ApplyParagraphPropertiesFromTableStyle(aTableInfo);
}
}
catch ( const lang::IllegalArgumentException &e )
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
index 16d2a0cc37cc..b454be94f563 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
@@ -91,7 +91,7 @@ public:
*/
void startTable(const TablePropertyMapPtr& pProps);
- void ApplyParaProperty(css::beans::PropertyValues aTableProperties, PropertyIds eId);
+ void ApplyParagraphPropertiesFromTableStyle(TableInfo & rInfo);
/// Handle end of table.
void endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart);
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 2489f50ba94e..716c14e8a5bf 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -704,7 +704,7 @@ const OUString DomainMapper_Impl::GetDefaultParaStyleName()
return m_sDefaultParaStyleName;
}
-uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara)
+uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara, bool* pIsDocDefault)
{
while(pEntry.get( ) )
{
@@ -714,6 +714,9 @@ uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleShee
pEntry->pProperties->getProperty(eId);
if( aProperty )
{
+ if (pIsDocDefault)
+ *pIsDocDefault = pEntry->pProperties->isDocDefault(eId);
+
return aProperty->second;
}
}
@@ -737,7 +740,12 @@ uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleShee
{
boost::optional<PropertyMap::Property> aProperty = pDefaultParaProps->getProperty(eId);
if ( aProperty )
+ {
+ if (pIsDocDefault)
+ *pIsDocDefault = true;
+
return aProperty->second;
+ }
}
}
if ( bDocDefaults && isCharacterProperty(eId) )
@@ -747,9 +755,18 @@ uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleShee
{
boost::optional<PropertyMap::Property> aProperty = pDefaultCharProps->getProperty(eId);
if ( aProperty )
+ {
+ if (pIsDocDefault)
+ *pIsDocDefault = true;
+
return aProperty->second;
+ }
}
}
+
+ if (pIsDocDefault)
+ *pIsDocDefault = false;
+
return uno::Any();
}
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index cf681ea34deb..955d806e5bab 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -716,7 +716,7 @@ public:
const OUString GetDefaultParaStyleName();
// specified style - including inherited properties. Indicate whether paragraph defaults should be checked.
- css::uno::Any GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara);
+ css::uno::Any GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara, bool* bIsDocDefault = nullptr);
// current paragraph style - including inherited properties
css::uno::Any GetPropertyFromParaStyleSheet(PropertyIds eId);
// context's character style - including inherited properties
diff --git a/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx
index 562f5f1795b1..35638f774c79 100644
--- a/writerfilter/source/dmapper/PropertyIds.cxx
+++ b/writerfilter/source/dmapper/PropertyIds.cxx
@@ -366,6 +366,11 @@ bool isCharacterProperty( const PropertyIds eId )
return eId > PROP_CHARACTER_STYLES && eId < PROP_CHARACTER_END;
}
+bool isParagraphProperty( const PropertyIds eId )
+{
+ return eId >= PROP_PARA_ADJUST && eId <= PROP_PARA_WIDOWS;
+}
+
} //namespace dmapper
} //namespace writerfilter
diff --git a/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx
index 6b3136fe10a5..392c25e68b5a 100644
--- a/writerfilter/source/dmapper/PropertyIds.hxx
+++ b/writerfilter/source/dmapper/PropertyIds.hxx
@@ -363,6 +363,8 @@ OUString getPropertyName(PropertyIds eId);
bool isCharacterProperty(const PropertyIds eId);
+bool isParagraphProperty(const PropertyIds eId);
+
} //namespace dmapper
} // namespace writerfilter
#endif
diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx
index 5d51a89e976a..f1448dbd4423 100644
--- a/writerfilter/source/dmapper/PropertyMap.cxx
+++ b/writerfilter/source/dmapper/PropertyMap.cxx
@@ -189,6 +189,14 @@ uno::Sequence< beans::PropertyValue > PropertyMap::GetPropertyValues( bool bChar
return comphelper::containerToSequence( m_aValues );
}
+std::vector< PropertyIds > PropertyMap::GetPropertyIds()
+{
+ std::vector< PropertyIds > aRet;
+ for ( const auto& rPropPair : m_vMap )
+ aRet.push_back( rPropPair.first );
+ return aRet;
+}
+
#ifdef DEBUG_WRITERFILTER
static void lcl_AnyToTag( const uno::Any& rAny )
{
@@ -227,7 +235,7 @@ static void lcl_AnyToTag( const uno::Any& rAny )
}
#endif
-void PropertyMap::Insert( PropertyIds eId, const uno::Any& rAny, bool bOverwrite, GrabBagType i_GrabBagType )
+void PropertyMap::Insert( PropertyIds eId, const uno::Any& rAny, bool bOverwrite, GrabBagType i_GrabBagType, bool bDocDefault )
{
#ifdef DEBUG_WRITERFILTER
const OUString& rInsert = getPropertyName(eId);
@@ -239,7 +247,7 @@ void PropertyMap::Insert( PropertyIds eId, const uno::Any& rAny, bool bOverwrite
#endif
if ( !bOverwrite )
- m_vMap.insert(std::make_pair(eId, PropValue(rAny, i_GrabBagType)));
+ m_vMap.insert(std::make_pair(eId, PropValue(rAny, i_GrabBagType, bDocDefault)));
else
m_vMap[eId] = PropValue(rAny, i_GrabBagType);
@@ -268,6 +276,15 @@ bool PropertyMap::isSet( PropertyIds eId) const
return m_vMap.find( eId ) != m_vMap.end();
}
+bool PropertyMap::isDocDefault( PropertyIds eId ) const
+{
+ std::map< PropertyIds, PropValue >::const_iterator aIter = m_vMap.find( eId );
+ if ( aIter == m_vMap.end() )
+ return false;
+ else
+ return aIter->second.getIsDocDefault();
+}
+
#ifdef DEBUG_WRITERFILTER
void PropertyMap::dumpXml() const
{
@@ -324,7 +341,12 @@ void PropertyMap::InsertProps( const PropertyMapPtr& rMap, const bool bOverwrite
for ( const auto& rPropPair : rMap->m_vMap )
{
if ( bOverwrite || !m_vMap.count(rPropPair.first) )
- m_vMap[rPropPair.first] = rPropPair.second;
+ {
+ if ( !bOverwrite && !rPropPair.second.getIsDocDefault() )
+ m_vMap.insert(std::make_pair(rPropPair.first, PropValue(rPropPair.second.getValue(), rPropPair.second.getGrabBagType(), true)));
+ else
+ m_vMap[rPropPair.first] = rPropPair.second;
+ }
}
insertTableProperties( rMap.get(), bOverwrite );
diff --git a/writerfilter/source/dmapper/PropertyMap.hxx b/writerfilter/source/dmapper/PropertyMap.hxx
index 6f16de26fe0a..9289534cc445 100644
--- a/writerfilter/source/dmapper/PropertyMap.hxx
+++ b/writerfilter/source/dmapper/PropertyMap.hxx
@@ -95,23 +95,35 @@ class PropValue
private:
css::uno::Any m_aValue;
GrabBagType m_GrabBagType;
+ bool m_bIsDocDefault;
public:
+ PropValue( const css::uno::Any& rValue, GrabBagType i_GrabBagType, bool bDocDefault )
+ : m_aValue( rValue )
+ , m_GrabBagType( i_GrabBagType )
+ , m_bIsDocDefault( bDocDefault )
+ {
+ }
+
PropValue( const css::uno::Any& rValue, GrabBagType i_GrabBagType )
: m_aValue( rValue )
, m_GrabBagType( i_GrabBagType )
+ , m_bIsDocDefault( false )
{
}
PropValue()
: m_aValue()
, m_GrabBagType( NO_GRAB_BAG )
+ , m_bIsDocDefault( false )
{
}
const css::uno::Any& getValue() const { return m_aValue; }
GrabBagType getGrabBagType() const { return m_GrabBagType; }
+
+ bool getIsDocDefault() const { return m_bIsDocDefault; }
};
class PropertyMap : public virtual SvRefBase
@@ -135,13 +147,15 @@ public:
// the contained properties are their Value.
css::uno::Sequence< css::beans::PropertyValue > GetPropertyValues( bool bCharGrabBag = true );
+ std::vector< PropertyIds > GetPropertyIds();
+
// Add property, optionally overwriting existing attributes
- void Insert( PropertyIds eId, const css::uno::Any& rAny, bool bOverwrite = true, GrabBagType i_GrabBagType = NO_GRAB_BAG );
+ void Insert( PropertyIds eId, const css::uno::Any& rAny, bool bOverwrite = true, GrabBagType i_GrabBagType = NO_GRAB_BAG, bool bDocDefault = false );
// Remove a named property from *this, does nothing if the property id has not been set
void Erase( PropertyIds eId);
- // Imports properties from pMap
+ // Imports properties from pMap (bOverwrite==false means m_bIsDocDefault=true setting)
void InsertProps( const tools::SvRef< PropertyMap >& rMap, const bool bOverwrite = true );
// Returns a copy of the property if it exists, .first is its PropertyIds and .second is its Value (type css::uno::Any)
@@ -149,6 +163,7 @@ public:
// Has the property named been set (via Insert)?
bool isSet( PropertyIds eId ) const;
+ bool isDocDefault( PropertyIds eId ) const;
const css::uno::Reference< css::text::XFootnote >& GetFootnote() const { return m_xFootnote; }
diff --git a/writerfilter/source/dmapper/StyleSheetTable.cxx b/writerfilter/source/dmapper/StyleSheetTable.cxx
index 08145c98ad2f..31373d988611 100644
--- a/writerfilter/source/dmapper/StyleSheetTable.cxx
+++ b/writerfilter/source/dmapper/StyleSheetTable.cxx
@@ -397,6 +397,11 @@ StyleSheetTable::~StyleSheetTable()
{
}
+void StyleSheetTable::SetDefaultParaProps(PropertyIds eId, const css::uno::Any& rAny)
+{
+ m_pImpl->m_pDefaultParaProps->Insert(eId, rAny, /*bOverwrite=*/false, NO_GRAB_BAG, /*bDocDefault=*/true);
+}
+
PropertyMapPtr const & StyleSheetTable::GetDefaultParaProps()
{
return m_pImpl->m_pDefaultParaProps;
@@ -692,7 +697,7 @@ void StyleSheetTable::lcl_sprm(Sprm & rSprm)
if ( nSprmId == NS_ooxml::LN_CT_DocDefaults_pPrDefault && m_pImpl->m_pDefaultParaProps.get() &&
!m_pImpl->m_pDefaultParaProps->isSet( PROP_PARA_TOP_MARGIN ) )
{
- m_pImpl->m_pDefaultParaProps->Insert( PROP_PARA_TOP_MARGIN, uno::makeAny( sal_Int32(0) ) );
+ SetDefaultParaProps( PROP_PARA_TOP_MARGIN, uno::makeAny( sal_Int32(0) ) );
}
m_pImpl->m_rDMapper.PopStyleSheetProperties();
applyDefaults( true );
@@ -999,7 +1004,7 @@ void StyleSheetTable::ApplyStyleSheets( const FontTablePtr& rFontTable )
else if( bParaStyle )
{
// Paragraph styles that don't inherit from some parent need to apply the DocDefaults
- pEntry->pProperties->InsertProps( m_pImpl->m_pDefaultParaProps, /*bAllowOverwrite=*/false );
+ pEntry->pProperties->InsertProps( m_pImpl->m_pDefaultParaProps, /*bOverwrite=*/false );
//now it's time to set the default parameters - for paragraph styles
//Fonts: Western first entry in font table
@@ -1467,13 +1472,13 @@ void StyleSheetTable::applyDefaults(bool bParaProperties)
if( bParaProperties && m_pImpl->m_pDefaultParaProps.get())
{
// tdf#87533 LO will have different defaults here, depending on the locale. Import with documented defaults
- m_pImpl->m_pDefaultParaProps->Insert(PROP_WRITING_MODE, uno::makeAny(sal_Int16(text::WritingMode_LR_TB)), /*bOverwrite=*/false);
- m_pImpl->m_pDefaultParaProps->Insert(PROP_PARA_ADJUST, uno::makeAny(sal_Int16(style::ParagraphAdjust_LEFT)), false);
+ SetDefaultParaProps(PROP_WRITING_MODE, uno::makeAny(sal_Int16(text::WritingMode_LR_TB)));
+ SetDefaultParaProps(PROP_PARA_ADJUST, uno::makeAny(sal_Int16(style::ParagraphAdjust_LEFT)));
// Widow/Orphan -> set both to two if not already set
uno::Any aTwo = uno::makeAny(sal_Int8(2));
- m_pImpl->m_pDefaultParaProps->Insert(PROP_PARA_WIDOWS, aTwo, /*bOverwrite=*/false);
- m_pImpl->m_pDefaultParaProps->Insert(PROP_PARA_ORPHANS, aTwo, false);
+ SetDefaultParaProps(PROP_PARA_WIDOWS, aTwo);
+ SetDefaultParaProps(PROP_PARA_ORPHANS, aTwo);
uno::Reference<style::XStyleFamiliesSupplier> xStylesSupplier(m_pImpl->m_xTextDocument, uno::UNO_QUERY);
uno::Reference<container::XNameAccess> xStyleFamilies = xStylesSupplier->getStyleFamilies();
diff --git a/writerfilter/source/dmapper/StyleSheetTable.hxx b/writerfilter/source/dmapper/StyleSheetTable.hxx
index 686779acbd71..ee621093079e 100644
--- a/writerfilter/source/dmapper/StyleSheetTable.hxx
+++ b/writerfilter/source/dmapper/StyleSheetTable.hxx
@@ -102,6 +102,7 @@ public:
OUString getOrCreateCharStyle( PropertyValueVector_t& rCharProperties, bool bAlwaysCreate );
+ void SetDefaultParaProps(PropertyIds eId, const css::uno::Any& rAny);
PropertyMapPtr const & GetDefaultParaProps();
/// Returns the default character properties.
PropertyMapPtr const & GetDefaultCharProps();
commit 53a11d841a2860e51125ccc5deb09a338b892902
Author: László Németh <nemeth at numbertext.org>
AuthorDate: Wed Oct 2 14:57:16 2019 +0200
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 10:59:00 2021 +0100
tdf#81100 DOCX import: repeat header according to table style
Table style based repeating table header wasn't repeated,
only direct table formatting.
(cherry picked from commit f9aac900ada3d507526eeeed5b51fc7a10ab4cae)
Conflicts:
sw/source/filter/ww8/docxattributeoutput.cxx
Change-Id: I119e6d32bf22c6c85a84aa42ae4cd6c5f60166b2
diff --git a/sw/qa/extras/ooxmlexport/data/tdf81100.docx b/sw/qa/extras/ooxmlexport/data/tdf81100.docx
index 61038d190c7e..cd46100f0556 100644
Binary files a/sw/qa/extras/ooxmlexport/data/tdf81100.docx and b/sw/qa/extras/ooxmlexport/data/tdf81100.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index 0736171dcfb0..e22b5ac0466f 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -938,6 +938,17 @@ DECLARE_OOXMLEXPORT_TEST(testTdf81100, "tdf81100.docx")
return;
// keep "repeat table header" setting of table styles
assertXPath(pXmlDoc, "/w:styles/w:style/w:tblStylePr/w:trPr/w:tblHeader", 4);
+
+ xmlDocPtr pDump = parseLayoutDump();
+ CPPUNIT_ASSERT_EQUAL(3, getPages());
+
+ // table starts on page 1 and finished on page 2
+ // and it has got only a single repeating header line
+ assertXPath(pDump, "/root/page[2]/body/tab[1]", 1);
+ assertXPath(pDump, "/root/page[2]/body/tab[1]/row", 2);
+ assertXPath(pDump, "/root/page[3]/body/tab", 1);
+ if (!mbExported) // TODO export tblHeader=false
+ assertXPath(pDump, "/root/page[3]/body/tab/row", 1);
}
DECLARE_OOXMLEXPORT_TEST(testTdf121597TrackedDeletionOfMultipleParagraphs, "tdf121597.odt")
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 0438a1e54caf..69e73dc6474e 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -3573,7 +3573,7 @@ void DocxAttributeOutput::StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t c
if ( pTable->GetRowsToRepeat( ) > pTableTextNodeInfoInner->getRow( ) )
m_pSerializer->singleElementNS( XML_w, XML_tblHeader,
FSNS( XML_w, XML_val ), "true",
- FSEND );
+ FSEND ); // TODO to overwrite table style may need explicit false
TableRowRedline( pTableTextNodeInfoInner );
TableHeight( pTableTextNodeInfoInner );
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index 349cf28f4284..a0b077282885 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -49,6 +49,18 @@ using namespace ::com::sun::star;
using namespace ::std;
#define DEF_BORDER_DIST 190 //0,19cm
+#define CNF_FIRST_ROW 0x800
+#define CNF_LAST_ROW 0x400
+#define CNF_FIRST_COLUMN 0x200
+#define CNF_LAST_COLUMN 0x100
+#define CNF_ODD_VBAND 0x080
+#define CNF_EVEN_VBAND 0x040
+#define CNF_ODD_HBAND 0x020
+#define CNF_EVEN_HBAND 0x010
+#define CNF_FIRST_ROW_LAST_COLUMN 0x008
+#define CNF_FIRST_ROW_FIRST_COLUMN 0x004
+#define CNF_LAST_ROW_LAST_COLUMN 0x002
+#define CNF_LAST_ROW_FIRST_COLUMN 0x001
DomainMapperTableHandler::DomainMapperTableHandler(
css::uno::Reference<css::text::XTextAppendAndConvert> const& xText,
@@ -429,6 +441,10 @@ TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo
m_aTableProperties->dumpXml();
TagLogger::getInstance().endElement();
#endif
+ // apply tblHeader setting of the table style
+ PropertyMapPtr pHeaderStyleProps = pTableStyle->GetProperties(CNF_FIRST_ROW);
+ if ( pHeaderStyleProps->getProperty(PROP_HEADER_ROW_COUNT) )
+ m_aTableProperties->Insert(PROP_HEADER_ROW_COUNT, uno::makeAny( sal_Int32(1)), false);
}
}
@@ -632,19 +648,6 @@ TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo
return pTableStyle;
}
-#define CNF_FIRST_ROW 0x800
-#define CNF_LAST_ROW 0x400
-#define CNF_FIRST_COLUMN 0x200
-#define CNF_LAST_COLUMN 0x100
-#define CNF_ODD_VBAND 0x080
-#define CNF_EVEN_VBAND 0x040
-#define CNF_ODD_HBAND 0x020
-#define CNF_EVEN_HBAND 0x010
-#define CNF_FIRST_ROW_LAST_COLUMN 0x008
-#define CNF_FIRST_ROW_FIRST_COLUMN 0x004
-#define CNF_LAST_ROW_LAST_COLUMN 0x002
-#define CNF_LAST_ROW_FIRST_COLUMN 0x001
-
CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(TableInfo & rInfo, std::vector<HorizontallyMergedCell>& rMerges)
{
#ifdef DEBUG_WRITERFILTER
diff --git a/writerfilter/source/dmapper/DomainMapperTableManager.cxx b/writerfilter/source/dmapper/DomainMapperTableManager.cxx
index bc38207bbbc5..2ee0a892cbe5 100644
--- a/writerfilter/source/dmapper/DomainMapperTableManager.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableManager.cxx
@@ -226,7 +226,16 @@ bool DomainMapperTableManager::sprm(Sprm & rSprm)
insertTableProps(pPropMap);
}
else
+ {
+ if ( nIntValue == 0 && m_nRow == 0 )
+ {
+ // explicit tblHeader=0 in the first row must overwrite table style
+ TablePropertyMapPtr pPropMap( new TablePropertyMap );
+ pPropMap->Insert( PROP_HEADER_ROW_COUNT, uno::makeAny(sal_Int32(0)));
+ insertTableProps(pPropMap);
+ }
m_nHeaderRepeat = -1;
+ }
if (nIntValue)
{
// Store the info that this is a header, we'll need that when we apply table styles.
diff --git a/writerfilter/source/dmapper/TblStylePrHandler.cxx b/writerfilter/source/dmapper/TblStylePrHandler.cxx
index cc4654d5de34..b4603e30482e 100644
--- a/writerfilter/source/dmapper/TblStylePrHandler.cxx
+++ b/writerfilter/source/dmapper/TblStylePrHandler.cxx
@@ -162,6 +162,7 @@ void TblStylePrHandler::lcl_sprm(Sprm & rSprm)
break;
case NS_ooxml::LN_CT_TrPrBase_tblHeader:
{
+ m_pProperties->Insert( PROP_HEADER_ROW_COUNT, uno::makeAny(sal_Int32(1)));
beans::PropertyValue aValue;
aValue.Name = "tblHeader";
aValue.Value <<= true;
commit 7792420601789c092c7a26262451b386a096d68b
Author: László Németh <nemeth at numbertext.org>
AuthorDate: Thu Sep 26 12:43:02 2019 +0200
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 10:58:53 2021 +0100
tdf#81100 DOCX: keep "repeat table header" table style setting
during round trip by grab-bagging //tblStylePr/trPr/tblHeader.
(cherry picked from commit 93ebf6a85f699e0594e05374ac37f8e582292d4f)
Conflicts:
sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
sw/source/filter/ww8/docxtablestyleexport.cxx
Change-Id: Id9d3150ca48031791aeda19c126bc4d4ac16fb8f
diff --git a/sw/qa/extras/ooxmlexport/data/tdf81100.docx b/sw/qa/extras/ooxmlexport/data/tdf81100.docx
new file mode 100644
index 000000000000..61038d190c7e
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf81100.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index 018aa8ccfcb8..0736171dcfb0 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -931,6 +931,15 @@ DECLARE_OOXMLEXPORT_TEST(testTdf58944RepeatingTableHeader, "tdf58944-repeating-t
parseDump("/root/page[2]/body/tab/row[2]/cell[1]/txt/text()"));
}
+DECLARE_OOXMLEXPORT_TEST(testTdf81100, "tdf81100.docx")
+{
+ xmlDocPtr pXmlDoc = parseExport("word/styles.xml");
+ if (!pXmlDoc)
+ return;
+ // keep "repeat table header" setting of table styles
+ assertXPath(pXmlDoc, "/w:styles/w:style/w:tblStylePr/w:trPr/w:tblHeader", 4);
+}
+
DECLARE_OOXMLEXPORT_TEST(testTdf121597TrackedDeletionOfMultipleParagraphs, "tdf121597.odt")
{
xmlDocPtr pXmlDoc = parseExport("word/document.xml");
diff --git a/sw/source/filter/ww8/docxtablestyleexport.cxx b/sw/source/filter/ww8/docxtablestyleexport.cxx
index 3a48ebd2f76a..a23b24215f1b 100644
--- a/sw/source/filter/ww8/docxtablestyleexport.cxx
+++ b/sw/source/filter/ww8/docxtablestyleexport.cxx
@@ -61,6 +61,8 @@ public:
void tableStylePSpacing(uno::Sequence<beans::PropertyValue>& rSpacing);
/// Export of w:tblPr.
void tableStyleTablePr(uno::Sequence<beans::PropertyValue>& rTablePr);
+ /// Export of w:trPr.
+ void tableStyleTrPr(const uno::Sequence<beans::PropertyValue>& rTrPr);
/// Export of w:tcPr.
void tableStyleTcPr(uno::Sequence<beans::PropertyValue>& rTcPr);
/// Export of w:tcBorders (and w:tblBorders).
@@ -552,6 +554,22 @@ void DocxTableStyleExport::Impl::tableStyleTablePr(uno::Sequence<beans::Property
m_pSerializer->endElementNS(XML_w, XML_tblPr);
}
+void DocxTableStyleExport::Impl::tableStyleTrPr(const uno::Sequence<beans::PropertyValue>& rTrPr)
+{
+ if (!rTrPr.hasElements())
+ return;
+
+ m_pSerializer->startElementNS(XML_w, XML_trPr, FSEND);
+
+ for (const auto& rProp : rTrPr)
+ {
+ if (rProp.Name == "tblHeader")
+ m_pSerializer->singleElementNS(XML_w, XML_tblHeader, FSEND);
+ }
+
+ m_pSerializer->endElementNS(XML_w, XML_trPr);
+}
+
void DocxTableStyleExport::Impl::tableStyleTcPr(uno::Sequence<beans::PropertyValue>& rTcPr)
{
if (!rTcPr.hasElements())
@@ -589,7 +607,7 @@ void DocxTableStyleExport::Impl::tableStyleTableStylePr(
return;
OUString aType;
- uno::Sequence<beans::PropertyValue> aPPr, aRPr, aTablePr, aTcPr;
+ uno::Sequence<beans::PropertyValue> aPPr, aRPr, aTablePr, aTrPr, aTcPr;
for (sal_Int32 i = 0; i < rTableStylePr.getLength(); ++i)
{
if (rTableStylePr[i].Name == "type")
@@ -600,6 +618,8 @@ void DocxTableStyleExport::Impl::tableStyleTableStylePr(
aRPr = rTableStylePr[i].Value.get<uno::Sequence<beans::PropertyValue>>();
else if (rTableStylePr[i].Name == "tblPr")
aTablePr = rTableStylePr[i].Value.get<uno::Sequence<beans::PropertyValue>>();
+ else if (rTableStylePr[i].Name == "trPr")
+ aTrPr = rTableStylePr[i].Value.get<uno::Sequence<beans::PropertyValue>>();
else if (rTableStylePr[i].Name == "tcPr")
aTcPr = rTableStylePr[i].Value.get<uno::Sequence<beans::PropertyValue>>();
}
@@ -616,6 +636,7 @@ void DocxTableStyleExport::Impl::tableStyleTableStylePr(
// Even if we have an empty container, write it out, as Word does.
m_pSerializer->singleElementNS(XML_w, XML_tblPr, FSEND);
}
+ tableStyleTrPr(aTrPr);
tableStyleTcPr(aTcPr);
m_pSerializer->endElementNS(XML_w, XML_tblStylePr);
diff --git a/writerfilter/source/dmapper/StyleSheetTable.cxx b/writerfilter/source/dmapper/StyleSheetTable.cxx
index 2d19297ad80f..08145c98ad2f 100644
--- a/writerfilter/source/dmapper/StyleSheetTable.cxx
+++ b/writerfilter/source/dmapper/StyleSheetTable.cxx
@@ -582,7 +582,7 @@ void StyleSheetTable::lcl_sprm(Sprm & rSprm)
pProperties->resolve(*pTblStylePrHandler);
StyleSheetEntry* pEntry = m_pImpl->m_pCurrentEntry.get();
TableStyleSheetEntry& rTableEntry = dynamic_cast<TableStyleSheetEntry&>(*pEntry);
- rTableEntry.AppendInteropGrabBag(pTblStylePrHandler->getInteropGrabBag("tcPr"));
+ rTableEntry.AppendInteropGrabBag(pTblStylePrHandler->getInteropGrabBag((nSprmId == NS_ooxml::LN_CT_Style_tcPr) ? OUString("tcPr") : OUString("trPr")));
// This is a <w:tcPr> directly under <w:style>, so it affects the whole table.
rTableEntry.pProperties->InsertProps(pTblStylePrHandler->getProperties());
diff --git a/writerfilter/source/dmapper/TblStylePrHandler.cxx b/writerfilter/source/dmapper/TblStylePrHandler.cxx
index d2e5bb2054ce..cc4654d5de34 100644
--- a/writerfilter/source/dmapper/TblStylePrHandler.cxx
+++ b/writerfilter/source/dmapper/TblStylePrHandler.cxx
@@ -137,6 +137,7 @@ void TblStylePrHandler::lcl_sprm(Sprm & rSprm)
bool bGrabBag = rSprm.getId() == NS_ooxml::LN_CT_PPrBase ||
rSprm.getId() == NS_ooxml::LN_EG_RPrBase ||
rSprm.getId() == NS_ooxml::LN_CT_TblPrBase ||
+ rSprm.getId() == NS_ooxml::LN_CT_TrPrBase ||
rSprm.getId() == NS_ooxml::LN_CT_TcPrBase;
if (bGrabBag)
{
@@ -151,12 +152,22 @@ void TblStylePrHandler::lcl_sprm(Sprm & rSprm)
aSavedGrabBag.push_back(getInteropGrabBag("rPr"));
else if (rSprm.getId() == NS_ooxml::LN_CT_TblPrBase)
aSavedGrabBag.push_back(getInteropGrabBag("tblPr"));
+ else if (rSprm.getId() == NS_ooxml::LN_CT_TrPrBase)
+ aSavedGrabBag.push_back(getInteropGrabBag("trPr"));
else if (rSprm.getId() == NS_ooxml::LN_CT_TcPrBase)
aSavedGrabBag.push_back(getInteropGrabBag("tcPr"));
std::swap(m_aInteropGrabBag, aSavedGrabBag);
}
}
break;
+ case NS_ooxml::LN_CT_TrPrBase_tblHeader:
+ {
+ beans::PropertyValue aValue;
+ aValue.Name = "tblHeader";
+ aValue.Value <<= true;
+ m_aInteropGrabBag.push_back(aValue);
+ }
+ break;
default:
// Tables specific properties have to handled here
m_pTablePropsHandler->SetProperties( m_pProperties );
commit b110d14f4d7110ce4af2e938bde354b033615c88
Author: László Németh <nemeth at numbertext.org>
AuthorDate: Tue Oct 8 13:25:10 2019 +0200
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 10:58:48 2021 +0100
tdf#127814 DOCX: fix default paragraph margin in table cells
when the table is started on a new page. Undefined
w:before in w:docDefaults/w:pPrDefault resulted 0.5 cm
paragraph top margin instead of 0 cm.
(cherry picked from commit 88ddeed17d5a7caca407f892a094a3dcb0aff501)
Conflicts:
sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
Change-Id: I94a2aa9e9c5fcee6443b74bb261c300c6a8e1303
diff --git a/sw/qa/extras/ooxmlexport/data/tdf127814.docx b/sw/qa/extras/ooxmlexport/data/tdf127814.docx
new file mode 100644
index 000000000000..10ed2348f166
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf127814.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
index 9aa780d01185..cd1665489db5 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
@@ -472,6 +472,15 @@ DECLARE_OOXMLEXPORT_TEST(testTdf119054, "tdf119054.docx")
assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "line", "240");
}
+DECLARE_OOXMLEXPORT_TEST(testTdf127814, "tdf127814.docx")
+{
+ // Paragraph top margin was 0 in a table started on a new page
+ xmlDocPtr pXmlDoc = parseExport();
+ if (!pXmlDoc)
+ return;
+ assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p/w:pPr/w:spacing", "before", "0");
+}
+
DECLARE_OOXMLEXPORT_TEST(testFdo69636, "fdo69636.docx")
{
/*
diff --git a/writerfilter/source/dmapper/StyleSheetTable.cxx b/writerfilter/source/dmapper/StyleSheetTable.cxx
index 957cdbedf356..2d19297ad80f 100644
--- a/writerfilter/source/dmapper/StyleSheetTable.cxx
+++ b/writerfilter/source/dmapper/StyleSheetTable.cxx
@@ -689,6 +689,11 @@ void StyleSheetTable::lcl_sprm(Sprm & rSprm)
case NS_ooxml::LN_CT_DocDefaults_pPrDefault:
m_pImpl->m_rDMapper.PushStyleSheetProperties( m_pImpl->m_pDefaultParaProps );
resolveSprmProps( m_pImpl->m_rDMapper, rSprm );
+ if ( nSprmId == NS_ooxml::LN_CT_DocDefaults_pPrDefault && m_pImpl->m_pDefaultParaProps.get() &&
+ !m_pImpl->m_pDefaultParaProps->isSet( PROP_PARA_TOP_MARGIN ) )
+ {
+ m_pImpl->m_pDefaultParaProps->Insert( PROP_PARA_TOP_MARGIN, uno::makeAny( sal_Int32(0) ) );
+ }
m_pImpl->m_rDMapper.PopStyleSheetProperties();
applyDefaults( true );
m_pImpl->m_bHasImportedDefaultParaProps = true;
commit 5194e808bbe987e634832344bd860b66777f60ca
Author: László Németh <nemeth at numbertext.org>
AuthorDate: Fri Nov 15 15:44:55 2019 +0100
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 10:58:39 2021 +0100
tdf#119054 DOCX: fix not table style based bottom margin
in table cells, ie. using paragraph styles with bottom
margin setting or direct paragraph formatting of bottom
margin. Both of them overwrite the table style based
bottom margin.
(cherry picked from commit 6100909c84550036932d031f4d2f652e158a1a0a)
Conflicts:
writerfilter/source/dmapper/DomainMapperTableHandler.cxx
Change-Id: I527b16c24fe47df8412291089ff86fadd3f9430b
diff --git a/sw/qa/extras/ooxmlexport/data/tdf119054.docx b/sw/qa/extras/ooxmlexport/data/tdf119054.docx
new file mode 100644
index 000000000000..9c3657c24a97
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf119054.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
index 910b14b00bb9..9aa780d01185 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
@@ -460,6 +460,18 @@ DECLARE_OOXMLEXPORT_TEST(testTdf128752, "tdf128752.docx")
assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "after", "0");
}
+DECLARE_OOXMLEXPORT_TEST(testTdf119054, "tdf119054.docx")
+{
+ xmlDocPtr pXmlDoc = parseExport();
+ if (!pXmlDoc)
+ return;
+ // Don't overwrite before and after spacing of Heading2 by table style
+ assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "before");
+ assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "after");
+ // Use table style based single line spacing instead of the docDefaults' 254
+ assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "line", "240");
+}
+
DECLARE_OOXMLEXPORT_TEST(testFdo69636, "fdo69636.docx")
{
/*
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index cbb46c29145a..349cf28f4284 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -807,6 +807,9 @@ CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(Tabl
// Remove properties from style/row that aren't allowed in cells
pAllCellProps->Erase( PROP_HEADER_ROW_COUNT );
pAllCellProps->Erase( PROP_TBL_HEADER );
+ // Remove paragraph properties from style/row that paragraph style can overwrite
+ pAllCellProps->Erase( PROP_PARA_BOTTOM_MARGIN );
+ pAllCellProps->Erase( PROP_PARA_LINE_SPACING );
// Then add the cell properties
pAllCellProps->InsertProps(*aCellIterator);
@@ -1010,6 +1013,36 @@ css::uno::Sequence<css::beans::PropertyValues> DomainMapperTableHandler::endTabl
return aRowProperties;
}
+// table style has got bigger precedence than docDefault style,
+// but lower precedence than the paragraph styles and direct paragraph formatting
+void DomainMapperTableHandler::ApplyParaProperty(css::beans::PropertyValues aTableProperties, PropertyIds eId)
+{
+ OUString sPropertyName = getPropertyName(eId);
+ auto pTableProp = std::find_if(aTableProperties.begin(), aTableProperties.end(),
+ [&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; });
+ if (pTableProp != aTableProperties.end())
+ {
+ uno::Any aValue = pTableProp->Value;
+ for (const auto& rParaProp : m_rDMapper_Impl.m_aParagraphsToEndTable)
+ {
+ // there is no direct paragraph formatting
+ if (!rParaProp.m_pPropertyMap->isSet(eId))
+ {
+ OUString sParaStyleName;
+ rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName;
+ StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName);
+ uno::Any aMargin = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true);
+ uno::Any aMarginDocDefault = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, nullptr, true, true);
+ // use table style only when 1) both values are empty (no docDefault and paragraph style definitions) or
+ // 2) both non-empty values are equal (docDefault paragraph properties are copied to the base paragraph style during import)
+ // TODO check the case, when two parent styles modify the docDefault and the last one set back the docDefault value
+ if (aMargin == aMarginDocDefault)
+ rParaProp.m_rPropertySet->setPropertyValue(sPropertyName, aValue);
+ }
+ }
+ }
+}
+
void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart)
{
#ifdef DEBUG_WRITERFILTER
@@ -1109,16 +1142,8 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
}
// OOXML table style may container paragraph properties, apply these now.
- for (int i = 0; i < aTableInfo.aTableProperties.getLength(); ++i)
- {
- if (aTableInfo.aTableProperties[i].Name == "ParaBottomMargin")
- {
- uno::Any aBottomMargin = aTableInfo.aTableProperties[i].Value;
-
- for (const auto& rParaProp : m_rDMapper_Impl.m_aPendingParaProp )
- rParaProp->setPropertyValue("ParaBottomMargin", aBottomMargin );
- }
- }
+ ApplyParaProperty(aTableInfo.aTableProperties, PROP_PARA_BOTTOM_MARGIN);
+ ApplyParaProperty(aTableInfo.aTableProperties, PROP_PARA_LINE_SPACING);
}
}
catch ( const lang::IllegalArgumentException &e )
@@ -1198,7 +1223,7 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
m_aCellProperties.clear();
m_aRowProperties.clear();
m_bHadFootOrEndnote = false;
- m_rDMapper_Impl.m_aPendingParaProp.clear();
+ m_rDMapper_Impl.m_aParagraphsToEndTable.clear();
#ifdef DEBUG_WRITERFILTER
TagLogger::getInstance().endElement();
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
index 7a45afa5c0b9..16d2a0cc37cc 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
@@ -90,6 +90,9 @@ public:
@param pProps properties of the table
*/
void startTable(const TablePropertyMapPtr& pProps);
+
+ void ApplyParaProperty(css::beans::PropertyValues aTableProperties, PropertyIds eId);
+
/// Handle end of table.
void endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart);
/**
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 9de2d6f46e69..2489f50ba94e 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -704,9 +704,9 @@ const OUString DomainMapper_Impl::GetDefaultParaStyleName()
return m_sDefaultParaStyleName;
}
-uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara, const bool bStyles)
+uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara)
{
- while( bStyles && pEntry.get( ) )
+ while(pEntry.get( ) )
{
if(pEntry->pProperties)
{
@@ -1526,6 +1526,15 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
}
css::uno::Reference<css::beans::XPropertySet> xParaProps(xTextRange, uno::UNO_QUERY);
+
+ // table style has got bigger precedence than docDefault style
+ // collect these pending paragraph properties to process in endTable()
+ if (xParaProps && m_nTableDepth > 0)
+ {
+ TableParagraph aPending{pParaContext, xParaProps};
+ m_aParagraphsToEndTable.push_back(aPending);
+ }
+
// tdf#118521 set paragraph top or bottom margin based on the paragraph style
// if we already set the other margin with direct formatting
if (xParaProps)
@@ -1546,16 +1555,7 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
{
uno::Any aMargin = GetPropertyFromParaStyleSheet(PROP_PARA_BOTTOM_MARGIN);
if ( aMargin != uno::Any() )
- {
xParaProps->setPropertyValue("ParaBottomMargin", aMargin);
-
- // table style has got bigger precedence than docDefault style
- // collect these pending paragraph properties to process in endTable()
- // TODO check the case, when two parent styles modify the docDefault and the last one set back the docDefault value
- uno::Any aMarginDocDefault = GetPropertyFromStyleSheet(PROP_PARA_BOTTOM_MARGIN, nullptr, true, true, false);
- if ( m_nTableDepth > 0 && aMargin == aMarginDocDefault )
- m_aPendingParaProp.push_back(xParaProps);
- }
}
if ( !bContextSet )
{
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index c07bda028d86..cf681ea34deb 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -397,6 +397,13 @@ struct SymbolData
{ }
};
+/// Information about a paragraph to be finished after a table end.
+struct TableParagraph
+{
+ PropertyMapPtr m_pPropertyMap;
+ css::uno::Reference<css::beans::XPropertySet> m_rPropertySet;
+};
+
class DomainMapper;
class DomainMapper_Impl final
{
@@ -709,7 +716,7 @@ public:
const OUString GetDefaultParaStyleName();
// specified style - including inherited properties. Indicate whether paragraph defaults should be checked.
- css::uno::Any GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara, const bool bStyles = true);
+ css::uno::Any GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara);
// current paragraph style - including inherited properties
css::uno::Any GetPropertyFromParaStyleSheet(PropertyIds eId);
// context's character style - including inherited properties
@@ -1006,7 +1013,7 @@ public:
void ClearPreviousParagraph();
/// Table paragraph properties may need style update based on table style
- std::vector<css::uno::Reference<css::beans::XPropertySet>> m_aPendingParaProp;
+ std::vector<TableParagraph> m_aParagraphsToEndTable;
private:
void PushPageHeaderFooter(bool bHeader, SectionPropertyMap::PageType eType);
commit 8bccf056883b8c178b11f0db0aa0c4843ee7418a
Author: László Németh <nemeth at numbertext.org>
AuthorDate: Fri Nov 15 11:58:01 2019 +0100
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 10:50:28 2021 +0100
DOCX: clean-up paragraph bottom handling of table style
Revert of commit 17e904ed66c3caf87e658b9d3a18d7b13f4a0b52
("bnc#816593 DOCX filter: import paragraph spacing from table style),
keeping only the working unit test.
(cherry picked from commit 00eeb7b3f765a51f51f7911a116982fbfb83efb7)
Conflicts:
writerfilter/source/dmapper/DomainMapperTableHandler.cxx
Change-Id: I735744aadb071ef2f0d939cb637d83cfc5716fe4
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index 61e088bfa4c1..cbb46c29145a 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -19,8 +19,6 @@
#include "DomainMapperTableHandler.hxx"
#include "DomainMapper_Impl.hxx"
#include "StyleSheetTable.hxx"
-#include <com/sun/star/beans/XPropertyState.hpp>
-#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/table/TableBorderDistances.hpp>
#include <com/sun/star/table/TableBorder.hpp>
#include <com/sun/star/table/BorderLine2.hpp>
@@ -1012,23 +1010,6 @@ css::uno::Sequence<css::beans::PropertyValues> DomainMapperTableHandler::endTabl
return aRowProperties;
}
-// Apply paragraph property to each paragraph within a cell.
-static void lcl_ApplyCellParaProps(uno::Reference<table::XCell> const& xCell,
- const uno::Any& rBottomMargin)
-{
- uno::Reference<container::XEnumerationAccess> xEnumerationAccess(xCell, uno::UNO_QUERY);
- uno::Reference<container::XEnumeration> xEnumeration = xEnumerationAccess->createEnumeration();
- while (xEnumeration->hasMoreElements())
- {
- uno::Reference<beans::XPropertySet> xParagraph(xEnumeration->nextElement(), uno::UNO_QUERY);
- uno::Reference<beans::XPropertyState> xPropertyState(xParagraph, uno::UNO_QUERY);
- // Don't apply in case direct formatting is already present.
- // TODO: probably paragraph style has priority over table style here.
- if (xPropertyState.is() && xPropertyState->getPropertyState("ParaBottomMargin") == beans::PropertyState_DEFAULT_VALUE)
- xParagraph->setPropertyValue("ParaBottomMargin", rBottomMargin);
- }
-}
-
void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart)
{
#ifdef DEBUG_WRITERFILTER
@@ -1132,21 +1113,10 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
{
if (aTableInfo.aTableProperties[i].Name == "ParaBottomMargin")
{
- uno::Reference<table::XCellRange> xCellRange(xTable, uno::UNO_QUERY);
uno::Any aBottomMargin = aTableInfo.aTableProperties[i].Value;
- sal_Int32 nRows = aCellProperties.getLength();
-
- for (const auto& rParaProp : m_rDMapper_Impl.m_aPendingParaProp )
- rParaProp->setPropertyValue("ParaBottomMargin", aBottomMargin );
- for (sal_Int32 nRow = 0; nRow < nRows; ++nRow)
- {
- const uno::Sequence< beans::PropertyValues > aCurrentRow = aCellProperties[nRow];
- sal_Int32 nCells = aCurrentRow.getLength();
- for (sal_Int32 nCell = 0; nCell < nCells; ++nCell)
- lcl_ApplyCellParaProps(xCellRange->getCellByPosition(nCell, nRow), aBottomMargin);
- }
- break;
+ for (const auto& rParaProp : m_rDMapper_Impl.m_aPendingParaProp )
+ rParaProp->setPropertyValue("ParaBottomMargin", aBottomMargin );
}
}
}
commit 1b6a7ca11869f0a80c08df4a7d1caac0c3ff02e5
Author: László Németh <nemeth at numbertext.org>
AuthorDate: Fri Nov 15 10:37:42 2019 +0100
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 10:50:20 2021 +0100
tdf#128752 DOCX: fix partial direct paragraph spacing in tables
When direct formatting of a table paragraph set only top margin,
but not the bottom margin, also there was no paragraph style setting
for the bottom margin, the paragraph was imported using docDefault
bottom spacing instead of the table style bottom spacing.
(cherry picked from commit d8f3f8ecd9e6304f3a98ab03fae6bc545893f782)
Conflicts:
sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
writerfilter/source/dmapper/DomainMapper_Impl.hxx
Change-Id: Ib7f5f80dd2485a0fd4ab8e0645b7d730a7ec3c5c
diff --git a/sw/qa/extras/ooxmlexport/data/tdf128752.docx b/sw/qa/extras/ooxmlexport/data/tdf128752.docx
new file mode 100644
index 000000000000..0e49291414d7
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf128752.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
index 94121b7e22b4..910b14b00bb9 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
@@ -451,6 +451,15 @@ DECLARE_OOXMLEXPORT_TEST(testTableFloatingMargins, "table-floating-margins.docx"
assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p/w:pPr/w:spacing", "after", "0");
}
+DECLARE_OOXMLEXPORT_TEST(testTdf128752, "tdf128752.docx")
+{
+ // Paragraph bottom margin was 200, docDefault instead of table style setting
+ xmlDocPtr pXmlDoc = parseExport();
+ if (!pXmlDoc)
+ return;
+ assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "after", "0");
+}
+
DECLARE_OOXMLEXPORT_TEST(testFdo69636, "fdo69636.docx")
{
/*
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index 67f33911f1c4..61e088bfa4c1 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -1135,6 +1135,10 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
uno::Reference<table::XCellRange> xCellRange(xTable, uno::UNO_QUERY);
uno::Any aBottomMargin = aTableInfo.aTableProperties[i].Value;
sal_Int32 nRows = aCellProperties.getLength();
+
+ for (const auto& rParaProp : m_rDMapper_Impl.m_aPendingParaProp )
+ rParaProp->setPropertyValue("ParaBottomMargin", aBottomMargin );
+
for (sal_Int32 nRow = 0; nRow < nRows; ++nRow)
{
const uno::Sequence< beans::PropertyValues > aCurrentRow = aCellProperties[nRow];
@@ -1224,6 +1228,7 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
m_aCellProperties.clear();
m_aRowProperties.clear();
m_bHadFootOrEndnote = false;
+ m_rDMapper_Impl.m_aPendingParaProp.clear();
#ifdef DEBUG_WRITERFILTER
TagLogger::getInstance().endElement();
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index ceb6d3fba0f3..9de2d6f46e69 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -704,9 +704,9 @@ const OUString DomainMapper_Impl::GetDefaultParaStyleName()
return m_sDefaultParaStyleName;
}
-uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara)
+uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara, const bool bStyles)
{
- while(pEntry.get( ) )
+ while( bStyles && pEntry.get( ) )
{
if(pEntry->pProperties)
{
@@ -1546,7 +1546,16 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
{
uno::Any aMargin = GetPropertyFromParaStyleSheet(PROP_PARA_BOTTOM_MARGIN);
if ( aMargin != uno::Any() )
+ {
xParaProps->setPropertyValue("ParaBottomMargin", aMargin);
+
+ // table style has got bigger precedence than docDefault style
+ // collect these pending paragraph properties to process in endTable()
+ // TODO check the case, when two parent styles modify the docDefault and the last one set back the docDefault value
+ uno::Any aMarginDocDefault = GetPropertyFromStyleSheet(PROP_PARA_BOTTOM_MARGIN, nullptr, true, true, false);
+ if ( m_nTableDepth > 0 && aMargin == aMarginDocDefault )
+ m_aPendingParaProp.push_back(xParaProps);
+ }
}
if ( !bContextSet )
{
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 258398255fb1..c07bda028d86 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -709,7 +709,7 @@ public:
const OUString GetDefaultParaStyleName();
// specified style - including inherited properties. Indicate whether paragraph defaults should be checked.
- css::uno::Any GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara);
+ css::uno::Any GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara, const bool bStyles = true);
// current paragraph style - including inherited properties
css::uno::Any GetPropertyFromParaStyleSheet(PropertyIds eId);
// context's character style - including inherited properties
@@ -1005,6 +1005,9 @@ public:
/// start/end node.
void ClearPreviousParagraph();
+ /// Table paragraph properties may need style update based on table style
+ std::vector<css::uno::Reference<css::beans::XPropertySet>> m_aPendingParaProp;
+
private:
void PushPageHeaderFooter(bool bHeader, SectionPropertyMap::PageType eType);
std::vector<css::uno::Reference< css::drawing::XShape > > m_vTextFramesForChaining ;
commit a56f3177fba49f2ead26f8f5a54e6d1c626d623b
Author: Justin Luth <justin.luth at collabora.com>
AuthorDate: Fri Oct 4 11:47:57 2019 +0300
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Fri Mar 5 10:50:15 2021 +0100
related tdf#99602 writerfilter TODO: subscript - use CharStyle fontsize
GetAnyProperty was missing a check for character style properties.
This patch depends on commit 875793d841165aaaaefa2c34b855e8f0f8a8c214
related tdf#99602 writerfilter TODO: subscript - use ParaStyle fontsize
and on commit 5e97d1a57717f8dbf69b987d2bda8616972eec52
NFC writerfilter: preparation for adding CharProps to GetAnyProperty
(cherry picked from commit 9b8052bba91ed616de77006cd0d3dee3965caece)
Conflicts:
sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
Change-Id: I4e28589917e41fa545d5aab05f97a67502486136
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 6df5464e436b..ceb6d3fba0f3 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -704,7 +704,7 @@ const OUString DomainMapper_Impl::GetDefaultParaStyleName()
return m_sDefaultParaStyleName;
}
-uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bPara)
+uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara)
{
while(pEntry.get( ) )
{
@@ -730,7 +730,7 @@ uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleShee
pEntry = pNewEntry;
}
// not found in style, try the document's DocDefault properties
- if ( bPara )
+ if ( bDocDefaults && bPara )
{
const PropertyMapPtr& pDefaultParaProps = GetStyleSheetTable()->GetDefaultParaProps();
if ( pDefaultParaProps )
@@ -740,7 +740,7 @@ uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleShee
return aProperty->second;
}
}
- if ( isCharacterProperty(eId) )
+ if ( bDocDefaults && isCharacterProperty(eId) )
{
const PropertyMapPtr& pDefaultCharProps = GetStyleSheetTable()->GetDefaultCharProps();
if ( pDefaultCharProps )
@@ -760,17 +760,40 @@ uno::Any DomainMapper_Impl::GetPropertyFromParaStyleSheet(PropertyIds eId)
pEntry = GetStyleSheetTable()->GetCurrentEntry();
else
pEntry = GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(GetCurrentParaStyleName());
- return GetPropertyFromStyleSheet(eId, pEntry, /*bPara=*/true);
+ return GetPropertyFromStyleSheet(eId, pEntry, /*bDocDefaults=*/true, /*bPara=*/true);
+}
+
+uno::Any DomainMapper_Impl::GetPropertyFromCharStyleSheet(PropertyIds eId, const PropertyMapPtr& rContext)
+{
+ if ( m_bInStyleSheetImport || eId == PROP_CHAR_STYLE_NAME || !isCharacterProperty(eId) )
+ return uno::Any();
+
+ StyleSheetEntryPtr pEntry;
+ OUString sCharStyleName;
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list