tdf#167326: Let CalcHeightWithFlys take hidden frame state into account
Table cells use that function to calculate the min cell height. In the bugdoc, sections inside a cell contained flys, and were hidden. When the min cell height was calculated, the sections' flys were considered, despite they were hidden. Change-Id: Ie5a8fb54a1c9fe21cc5f4d474bd24feabb660330 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192232 Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> Tested-by: Jenkins
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text">
|
||||
<office:automatic-styles>
|
||||
<style:style style:name="gr1" style:family="graphic">
|
||||
<style:graphic-properties style:wrap="none" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph" style:flow-with-text="true"/>
|
||||
</style:style>
|
||||
</office:automatic-styles>
|
||||
<office:body>
|
||||
<office:text>
|
||||
<table:table>
|
||||
<table:table-column/>
|
||||
<table:table-row>
|
||||
<table:table-cell office:value-type="string">
|
||||
<text:p>In this cell, below, there is a section with a shape:</text:p>
|
||||
<text:section text:name="Sect1">
|
||||
<text:p><draw:custom-shape text:anchor-type="char" draw:name="Shape1" draw:style-name="gr1" svg:width="5cm" svg:height="5cm" svg:x="0" svg:y="0">
|
||||
<draw:enhanced-geometry draw:type="rectangle"/>
|
||||
</draw:custom-shape></text:p>
|
||||
</text:section>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
</table:table>
|
||||
</office:text>
|
||||
</office:body>
|
||||
</office:document>
|
||||
@@ -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<css::text::XTextSectionsSupplier>();
|
||||
auto xSections = xTextSectionsSupplier->getTextSections();
|
||||
CPPUNIT_ASSERT(xSections);
|
||||
auto xSection = xSections->getByName(u"Sect1"_ustr).queryThrow<css::beans::XPropertySet>();
|
||||
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)
|
||||
|
||||
+126
-112
@@ -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<const SwTextFrame*>(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<const SwTextFrame*>(pTmp);
|
||||
if ( pTmpFrame->GetPrev() && pTmpFrame->GetPrev()->IsTextFrame() &&
|
||||
static_cast<const SwTextFrame*>(pTmpFrame->GetPrev())->GetFollow() &&
|
||||
static_cast<const SwTextFrame*>(pTmpFrame->GetPrev())->GetFollow() != pTmp )
|
||||
pMaster = nullptr;
|
||||
else
|
||||
pMaster = pTmpFrame->FindMaster();
|
||||
|
||||
if ( pMaster )
|
||||
{
|
||||
pObjs = static_cast<const SwTextFrame*>(pTmp)->FindMaster()->GetDrawObjs();
|
||||
bIsFollow = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pObjs = pTmp->GetDrawObjs();
|
||||
}
|
||||
if ( pObjs )
|
||||
{
|
||||
for (SwAnchoredObject* pAnchoredObj : *pObjs)
|
||||
{
|
||||
// #i26945# - if <pTmp> is follow, the
|
||||
// anchor character frame has to be <pTmp>.
|
||||
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<const SwSectionFrame*>(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<const SwTextFrame*>(pTmp)->IsFollow() )
|
||||
if (pFrame->IsHiddenNow())
|
||||
return 0;
|
||||
tools::Long nHeight = 0;
|
||||
const SwFrame* pTmp = static_cast<const SwSectionFrame*>(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<const SwTextFrame*>(pTmp);
|
||||
if ( pTmpFrame->GetPrev() && pTmpFrame->GetPrev()->IsTextFrame() &&
|
||||
static_cast<const SwTextFrame*>(pTmpFrame->GetPrev())->GetFollow() &&
|
||||
static_cast<const SwTextFrame*>(pTmpFrame->GetPrev())->GetFollow() != pTmp )
|
||||
pMaster = nullptr;
|
||||
else
|
||||
pMaster = pTmpFrame->FindMaster();
|
||||
|
||||
if ( pMaster )
|
||||
{
|
||||
pObjs = static_cast<const SwTextFrame*>(pTmp)->FindMaster()->GetDrawObjs();
|
||||
bIsFollow = true;
|
||||
}
|
||||
nHeight += CalcHeightWithFlys_Impl(pTmp, pFrame, aRectFnSet);
|
||||
pTmp = pTmp->FindNextCnt();
|
||||
if (!static_cast<const SwSectionFrame*>(pFrame)->IsAnLower(pTmp))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
pObjs = pTmp->GetDrawObjs();
|
||||
}
|
||||
if ( pObjs )
|
||||
{
|
||||
for (SwAnchoredObject* pAnchoredObj : *pObjs)
|
||||
{
|
||||
// #i26945# - if <pTmp> is follow, the
|
||||
// anchor character frame has to be <pTmp>.
|
||||
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<const SwSectionFrame*>(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 )
|
||||
|
||||
Reference in New Issue
Block a user