diff --git a/sw/qa/extras/layout/data/tdf167326.fodt b/sw/qa/extras/layout/data/tdf167326.fodt
new file mode 100644
index 000000000000..5004f9ed9cbf
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf167326.fodt
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ In this cell, below, there is a section with a shape:
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sw/qa/extras/layout/layout4.cxx b/sw/qa/extras/layout/layout4.cxx
index 421ddfd93521..7fb98e772d11 100644
--- a/sw/qa/extras/layout/layout4.cxx
+++ b/sw/qa/extras/layout/layout4.cxx
@@ -1443,6 +1443,33 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter4, testTdf160958_orphans)
assertXPath(pExportDump, "//page[2]/body/txt[1]/SwParaPortion/SwLineLayout", 1);
}
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter4, testTdf167326)
+{
+ // A document with a table with a section with a to-char no-wrap keep-inside-boundaries shape
+ createSwDoc("tdf167326.fodt");
+ auto pExportDump = parseLayoutDump();
+ assertXPath(pExportDump, "//tab", 1);
+ OUString height = getXPath(pExportDump, "//tab/infos/bounds", "height");
+ // Expected height: ~3388 = shape 2836 + 2 * text ~276
+ CPPUNIT_ASSERT_GREATER(sal_Int32(3000), height.toInt32());
+
+ // Hide the section
+ auto xTextSectionsSupplier = mxComponent.queryThrow();
+ auto xSections = xTextSectionsSupplier->getTextSections();
+ CPPUNIT_ASSERT(xSections);
+ auto xSection = xSections->getByName(u"Sect1"_ustr).queryThrow();
+ xSection->setPropertyValue(u"IsVisible"_ustr, css::uno::Any(false));
+
+ calcLayout();
+ pExportDump = parseLayoutDump();
+ assertXPath(pExportDump, "//tab", 1);
+ height = getXPath(pExportDump, "//tab/infos/bounds", "height");
+ // Expected height: ~276 = 1 * text ~276
+ // Without the fix, this was ~3111, because calculation of table cell's height considered
+ // height of section's shape, not taking its visibility into account.
+ CPPUNIT_ASSERT_LESS(sal_Int32(500), height.toInt32());
+}
+
CPPUNIT_TEST_FIXTURE(SwLayoutWriter4, testTdf161368)
{
// Given a document with a text body width of 116 mm, greater than 65535 twips (115.6 mm)
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index d79568dcf44e..a08ce1af68e2 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -4789,125 +4789,139 @@ void SwRowFrame::dumpAsXml(xmlTextWriterPtr writer) const
(void)xmlTextWriterEndElement(writer);
}
+static tools::Long CalcHeightWithFlys_Impl(const SwFrame* pTmp, const SwFrame* pFrame,
+ const SwRectFnSet& aRectFnSet)
+{
+ if (pFrame->IsHiddenNow())
+ return 0;
+ tools::Long nHeight = 0;
+ // #i26945# - consider follow text frames
+ const SwSortedObjs* pObjs( nullptr );
+ bool bIsFollow( false );
+ if ( pTmp->IsTextFrame() && static_cast(pTmp)->IsFollow() )
+ {
+ const SwFrame* pMaster;
+ // #i46450# Master does not necessarily have
+ // to exist if this function is called from JoinFrame() ->
+ // Cut() -> Shrink()
+ const SwTextFrame* pTmpFrame = static_cast(pTmp);
+ if ( pTmpFrame->GetPrev() && pTmpFrame->GetPrev()->IsTextFrame() &&
+ static_cast(pTmpFrame->GetPrev())->GetFollow() &&
+ static_cast(pTmpFrame->GetPrev())->GetFollow() != pTmp )
+ pMaster = nullptr;
+ else
+ pMaster = pTmpFrame->FindMaster();
+
+ if ( pMaster )
+ {
+ pObjs = static_cast(pTmp)->FindMaster()->GetDrawObjs();
+ bIsFollow = true;
+ }
+ }
+ else
+ {
+ pObjs = pTmp->GetDrawObjs();
+ }
+ if ( pObjs )
+ {
+ for (SwAnchoredObject* pAnchoredObj : *pObjs)
+ {
+ // #i26945# - if is follow, the
+ // anchor character frame has to be .
+ if ( bIsFollow &&
+ pAnchoredObj->FindAnchorCharFrame() != pTmp )
+ {
+ continue;
+ }
+ // #i26945# - consider also drawing objects
+ {
+ // OD 30.09.2003 #i18732# - only objects, which follow
+ // the text flow have to be considered.
+ const SwFrameFormat* pFrameFormat = pAnchoredObj->GetFrameFormat();
+ bool bFollowTextFlow = pFrameFormat->GetFollowTextFlow().GetValue();
+ bool bIsFarAway = pAnchoredObj->GetObjRect().Top() != FAR_AWAY;
+ const SwPageFrame* pPageFrm = pTmp->FindPageFrame();
+ bool bIsAnchoredToTmpFrm = false;
+ if ( pPageFrm && pPageFrm->IsPageFrame() && pAnchoredObj->GetPageFrame())
+ bIsAnchoredToTmpFrm = pAnchoredObj->GetPageFrame() == pPageFrm ||
+ (pPageFrm->GetFormatPage().GetPhyPageNum() == pAnchoredObj->GetPageFrame()->GetFormatPage().GetPhyPageNum() + 1);
+ const bool bConsiderObj =
+ (pFrameFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR) &&
+ bIsFarAway &&
+ bFollowTextFlow && bIsAnchoredToTmpFrm;
+ bool bWrapThrough = pFrameFormat->GetSurround().GetValue() == text::WrapTextMode_THROUGH;
+ bool bInBackground = !pFrameFormat->GetOpaque().GetValue();
+ // Legacy render requires in-background setting, the new mode does not.
+ bool bConsiderFollowTextFlow = bInBackground
+ || !pFrameFormat->getIDocumentSettingAccess().get(
+ DocumentSettingId::USE_FORMER_TEXT_WRAPPING);
+ if (pFrame->IsInTab() && bFollowTextFlow && bWrapThrough && bConsiderFollowTextFlow)
+ {
+ // Ignore wrap-through objects when determining the cell height.
+ // Normally FollowTextFlow requires a resize of the cell, but not in case of
+ // wrap-through.
+ continue;
+ }
+
+ if ( bConsiderObj )
+ {
+ const SwFormatFrameSize &rSz = pFrameFormat->GetFrameSize();
+ if( !rSz.GetHeightPercent() )
+ {
+ const SwTwips nDistOfFlyBottomToAnchorTop =
+ aRectFnSet.GetHeight(pAnchoredObj->GetObjRect()) +
+ ( aRectFnSet.IsVert() ?
+ pAnchoredObj->GetCurrRelPos().X() :
+ pAnchoredObj->GetCurrRelPos().Y() );
+
+ const SwTwips nFrameDiff =
+ aRectFnSet.YDiff(
+ aRectFnSet.GetTop(pTmp->getFrameArea()),
+ aRectFnSet.GetTop(pFrame->getFrameArea()) );
+
+ nHeight = std::max( nHeight, nDistOfFlyBottomToAnchorTop + nFrameDiff -
+ aRectFnSet.GetHeight(pFrame->getFrameArea()) );
+
+ // #i56115# The first height calculation
+ // gives wrong results if pFrame->getFramePrintArea().Y() > 0. We do
+ // a second calculation based on the actual rectangles of
+ // pFrame and pAnchoredObj, and use the maximum of the results.
+ // I do not want to remove the first calculation because
+ // if clipping has been applied, using the GetCurrRelPos
+ // might be the better option to calculate nHeight.
+ const SwTwips nDistOfFlyBottomToAnchorTop2 = aRectFnSet.YDiff(
+ aRectFnSet.GetBottom(pAnchoredObj->GetObjRect()),
+ aRectFnSet.GetBottom(pFrame->getFrameArea()) );
+
+ nHeight = std::max( nHeight, tools::Long(nDistOfFlyBottomToAnchorTop2 ));
+ }
+ }
+ }
+ }
+ }
+ return nHeight;
+}
+
tools::Long CalcHeightWithFlys( const SwFrame *pFrame )
{
SwRectFnSet aRectFnSet(pFrame);
- tools::Long nHeight = 0;
- const SwFrame* pTmp = pFrame->IsSctFrame() ?
- static_cast(pFrame)->ContainsContent() : pFrame;
- while( pTmp )
+ if (pFrame->IsSctFrame())
{
- // #i26945# - consider follow text frames
- const SwSortedObjs* pObjs( nullptr );
- bool bIsFollow( false );
- if ( pTmp->IsTextFrame() && static_cast(pTmp)->IsFollow() )
+ if (pFrame->IsHiddenNow())
+ return 0;
+ tools::Long nHeight = 0;
+ const SwFrame* pTmp = static_cast(pFrame)->ContainsContent();
+ while (pTmp)
{
- const SwFrame* pMaster;
- // #i46450# Master does not necessarily have
- // to exist if this function is called from JoinFrame() ->
- // Cut() -> Shrink()
- const SwTextFrame* pTmpFrame = static_cast(pTmp);
- if ( pTmpFrame->GetPrev() && pTmpFrame->GetPrev()->IsTextFrame() &&
- static_cast(pTmpFrame->GetPrev())->GetFollow() &&
- static_cast(pTmpFrame->GetPrev())->GetFollow() != pTmp )
- pMaster = nullptr;
- else
- pMaster = pTmpFrame->FindMaster();
-
- if ( pMaster )
- {
- pObjs = static_cast(pTmp)->FindMaster()->GetDrawObjs();
- bIsFollow = true;
- }
+ nHeight += CalcHeightWithFlys_Impl(pTmp, pFrame, aRectFnSet);
+ pTmp = pTmp->FindNextCnt();
+ if (!static_cast(pFrame)->IsAnLower(pTmp))
+ break;
}
- else
- {
- pObjs = pTmp->GetDrawObjs();
- }
- if ( pObjs )
- {
- for (SwAnchoredObject* pAnchoredObj : *pObjs)
- {
- // #i26945# - if is follow, the
- // anchor character frame has to be .
- if ( bIsFollow &&
- pAnchoredObj->FindAnchorCharFrame() != pTmp )
- {
- continue;
- }
- // #i26945# - consider also drawing objects
- {
- // OD 30.09.2003 #i18732# - only objects, which follow
- // the text flow have to be considered.
- const SwFrameFormat* pFrameFormat = pAnchoredObj->GetFrameFormat();
- bool bFollowTextFlow = pFrameFormat->GetFollowTextFlow().GetValue();
- bool bIsFarAway = pAnchoredObj->GetObjRect().Top() != FAR_AWAY;
- const SwPageFrame* pPageFrm = pTmp->FindPageFrame();
- bool bIsAnchoredToTmpFrm = false;
- if ( pPageFrm && pPageFrm->IsPageFrame() && pAnchoredObj->GetPageFrame())
- bIsAnchoredToTmpFrm = pAnchoredObj->GetPageFrame() == pPageFrm ||
- (pPageFrm->GetFormatPage().GetPhyPageNum() == pAnchoredObj->GetPageFrame()->GetFormatPage().GetPhyPageNum() + 1);
- const bool bConsiderObj =
- (pFrameFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR) &&
- bIsFarAway &&
- bFollowTextFlow && bIsAnchoredToTmpFrm;
- bool bWrapThrough = pFrameFormat->GetSurround().GetValue() == text::WrapTextMode_THROUGH;
- bool bInBackground = !pFrameFormat->GetOpaque().GetValue();
- // Legacy render requires in-background setting, the new mode does not.
- bool bConsiderFollowTextFlow = bInBackground
- || !pFrameFormat->getIDocumentSettingAccess().get(
- DocumentSettingId::USE_FORMER_TEXT_WRAPPING);
- if (pFrame->IsInTab() && bFollowTextFlow && bWrapThrough && bConsiderFollowTextFlow)
- {
- // Ignore wrap-through objects when determining the cell height.
- // Normally FollowTextFlow requires a resize of the cell, but not in case of
- // wrap-through.
- continue;
- }
-
- if ( bConsiderObj )
- {
- const SwFormatFrameSize &rSz = pFrameFormat->GetFrameSize();
- if( !rSz.GetHeightPercent() )
- {
- const SwTwips nDistOfFlyBottomToAnchorTop =
- aRectFnSet.GetHeight(pAnchoredObj->GetObjRect()) +
- ( aRectFnSet.IsVert() ?
- pAnchoredObj->GetCurrRelPos().X() :
- pAnchoredObj->GetCurrRelPos().Y() );
-
- const SwTwips nFrameDiff =
- aRectFnSet.YDiff(
- aRectFnSet.GetTop(pTmp->getFrameArea()),
- aRectFnSet.GetTop(pFrame->getFrameArea()) );
-
- nHeight = std::max( nHeight, nDistOfFlyBottomToAnchorTop + nFrameDiff -
- aRectFnSet.GetHeight(pFrame->getFrameArea()) );
-
- // #i56115# The first height calculation
- // gives wrong results if pFrame->getFramePrintArea().Y() > 0. We do
- // a second calculation based on the actual rectangles of
- // pFrame and pAnchoredObj, and use the maximum of the results.
- // I do not want to remove the first calculation because
- // if clipping has been applied, using the GetCurrRelPos
- // might be the better option to calculate nHeight.
- const SwTwips nDistOfFlyBottomToAnchorTop2 = aRectFnSet.YDiff(
- aRectFnSet.GetBottom(pAnchoredObj->GetObjRect()),
- aRectFnSet.GetBottom(pFrame->getFrameArea()) );
-
- nHeight = std::max( nHeight, tools::Long(nDistOfFlyBottomToAnchorTop2 ));
- }
- }
- }
- }
- }
- if( !pFrame->IsSctFrame() )
- break;
- pTmp = pTmp->FindNextCnt();
- if( !static_cast(pFrame)->IsAnLower( pTmp ) )
- break;
+ return nHeight;
}
- return nHeight;
+ // Not a section frame
+ return CalcHeightWithFlys_Impl(pFrame, pFrame, aRectFnSet);
}
static SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrame& rCell, const SwBorderAttrs& rAttrs )