d1c5ed30d1
... and use it in SwTextFrameBreak::IsBreakNow to decide if the content needs to go to a follow or not. The problem was, that in a specific case of the bugdoc, the follow text line was taller than the fixed row height on that page; that resulted in an attempt to break it again, creating an empty follow in the same table cell; it was not moved to the next page, detecting the problem in SwTextFrame::CalcFollow, and the formatting looped, until loop control fired, calling SwLooping::Drastic, which validated all page's content, including tables below, that had invalid zero client (prn) height. It was very difficult to tell when the break is needed, and when it's not, without the information why some frame eventually denied growing its height by the requested amount. In the bugdoc case, I failed to find at the SwTextFrameBreak::IsBreakNow level anything that could be used as a reliable distinction; some heuristic conditions used there broke layout in unit tests left and right. So eventually, I came with this mechanism of reporting the "why I can't grow" reason back to the caller, using the new out argument. I believe that, beyond this use case, it might be useful in many other cases, both to ease the decision, and to prevent needless trial-and- error iterations, increasing stability and performance. The enum used for the reason reporting includes 'FlowToFollow' and 'BalancedColumns', that could be used in those other cases. However, for my needs here, I only need the FixedSizeFrame reason, telling that it's not a case when breaking to a next frame is possible, so preventing the break. The choice of reported reasons in this patch is mostly best guess; it may be wrong in some places. The crucial for the current fix is the assignment inside the '!(GetType() & nTmpType) && HasFixSize()' check of SwLayoutFrame::GrowFrame. Change-Id: I9ce5dd4d2298b60e186fdf485efb85ab304308ee Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172362 Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> Tested-by: Jenkins
94 lines
3.2 KiB
C++
94 lines
3.2 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
#pragma once
|
|
|
|
#include <swtypes.hxx>
|
|
#include "itrtxt.hxx"
|
|
|
|
class SwTextFrame;
|
|
|
|
class SwTextFrameBreak
|
|
{
|
|
private:
|
|
SwTwips m_nRstHeight;
|
|
SwTwips m_nOrigin;
|
|
protected:
|
|
SwTextFrame *m_pFrame;
|
|
bool m_bBreak;
|
|
bool m_bKeep;
|
|
public:
|
|
SwTextFrameBreak( SwTextFrame *pFrame, const SwTwips nRst = 0 );
|
|
bool IsBreakNow( SwTextMargin &rLine );
|
|
bool IsKeepAlways() const { return m_bKeep; }
|
|
|
|
void SetKeep( const bool bNew ) { m_bKeep = bNew; }
|
|
|
|
bool IsInside( SwTextMargin const &rLine ) const;
|
|
bool IsInside(SwTextMargin const& rLine, SwResizeLimitReason&) const;
|
|
|
|
// In order to be able to handle special cases with Footnote.
|
|
// SetRstHeight sets the rest height for SwTextFrameBreak. This is needed
|
|
// to call TruncLines() without IsBreakNow() returning another value.
|
|
// We assume that rLine is pointing to the last non-fitting line.
|
|
|
|
void SetRstHeight( const SwTextMargin &rLine );
|
|
};
|
|
|
|
class WidowsAndOrphans : public SwTextFrameBreak
|
|
{
|
|
private:
|
|
sal_uInt16 m_nWidLines, m_nOrphLines;
|
|
|
|
public:
|
|
WidowsAndOrphans( SwTextFrame *pFrame, const SwTwips nRst = 0,
|
|
bool bCheckKeep = true );
|
|
bool FindWidows( SwTextFrame *pFrame, SwTextMargin &rLine );
|
|
sal_uInt16 GetOrphansLines() const
|
|
{ return m_nOrphLines; }
|
|
void ClrOrphLines(){ m_nOrphLines = 0; }
|
|
|
|
bool FindBreak( SwTextFrame *pFrame, SwTextMargin &rLine, bool bHasToFit );
|
|
bool WouldFit( SwTextMargin &rLine, SwTwips &rMaxHeight, bool bTest, bool bMoveBwd );
|
|
// i#16128 - This method is named this way to avoid confusion with
|
|
// base class method <SwTextFrameBreak::IsBreakNow>, which isn't virtual.
|
|
bool IsBreakNowWidAndOrp( SwTextMargin &rLine )
|
|
{
|
|
bool isOnFirstLine = (rLine.GetLineNr() == 1 && !rLine.GetPrev());
|
|
if ( isOnFirstLine && rLine.GetCurr()->IsDummy()) {
|
|
return IsBreakNow( rLine );
|
|
}
|
|
if ( rLine.GetLineNr() > m_nOrphLines ) {
|
|
return IsBreakNow( rLine );
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
inline bool SwTextFrameBreak::IsInside(SwTextMargin const& rLine) const
|
|
{
|
|
return IsInside(rLine, o3tl::temporary(SwResizeLimitReason()));
|
|
}
|
|
|
|
namespace sw {
|
|
|
|
auto FindNonFlyPortion(SwLineLayout const& rLine) -> bool;
|
|
|
|
} // namespace sw
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|