diff options
Diffstat (limited to 'sw/source')
-rw-r--r-- | sw/source/core/inc/cellfrm.hxx | 6 | ||||
-rw-r--r-- | sw/source/core/layout/paintfrm.cxx | 64 | ||||
-rw-r--r-- | sw/source/core/layout/tabfrm.cxx | 84 |
3 files changed, 154 insertions, 0 deletions
diff --git a/sw/source/core/inc/cellfrm.hxx b/sw/source/core/inc/cellfrm.hxx index d2f8730691ed..e8f894af3058 100644 --- a/sw/source/core/inc/cellfrm.hxx +++ b/sw/source/core/inc/cellfrm.hxx @@ -62,6 +62,12 @@ public: const SwCellFrame& FindStartEndOfRowSpanCell( bool bStart ) const; tools::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 c549b5ffeb46..e90ab0bad378 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -2241,11 +2241,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, @@ -2253,6 +2256,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); }; } @@ -2264,6 +2273,7 @@ SwLineEntry::SwLineEntry( SwTwips nKey, : mnKey( nKey ), mnStartPos( nStartPos ), mnEndPos( nEndPos ), + mnLimitedEndPos(0), maAttribute( rAttribute ) { } @@ -2317,6 +2327,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(); + } +} + namespace { struct lt_SwLineEntry @@ -2460,6 +2501,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: @@ -2780,8 +2827,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, @@ -2812,6 +2868,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 e6c8c2bc1a66..25b69f680b58 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -5497,6 +5497,90 @@ tools::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); |