diff --git a/sw/qa/extras/layout/data/tdf163060.fodt b/sw/qa/extras/layout/data/tdf163060.fodt
new file mode 100644
index 000000000000..a5f7291e09a5
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf163060.fodt
@@ -0,0 +1,205 @@
+
+
+
+
+
+ 0
+ 0
+ 27481
+ 16293
+ true
+ false
+
+
+ view2
+ 21758
+ 2300
+ 0
+ 0
+ 27480
+ 16291
+ 0
+ 1
+ false
+ 140
+ false
+ false
+ false
+ false
+ false
+ false
+
+
+
+
+ false
+ true
+ true
+
+ false
+ 0
+ false
+ true
+ false
+ true
+ false
+ false
+ true
+ 0
+ true
+ false
+ false
+ false
+ true
+ false
+ true
+ false
+ false
+ false
+ false
+ true
+ true
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ false
+ false
+ false
+ high-resolution
+ true
+ 2040775
+ false
+ false
+ false
+
+
+ true
+
+ false
+ false
+ false
+ true
+ true
+ true
+ false
+ 0
+ true
+ false
+ true
+ false
+ true
+ false
+ false
+ true
+ true
+ false
+ false
+ false
+ false
+ true
+ true
+ true
+
+ false
+ false
+ true
+ 0
+ false
+ true
+
+ false
+ false
+ true
+ true
+ false
+ false
+ false
+ 1
+ true
+ true
+ true
+ false
+ false
+ true
+ false
+ false
+ true
+ false
+ true
+ false
+ false
+
+ true
+ 2246101
+ true
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Quis pretium semper. Proin luctus orci a neque venenatis, quis commodo dolorsi
+
+
+
diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx
index 1f9358147e9f..852a213fbc03 100644
--- a/sw/qa/extras/layout/layout3.cxx
+++ b/sw/qa/extras/layout/layout3.cxx
@@ -389,6 +389,32 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf163042)
CPPUNIT_ASSERT_EQUAL(static_cast(158), aPosition.GetContentIndex());
}
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf163060)
+{
+ createSwDoc("tdf163060.fodt");
+
+ // Ensure that all text portions are calculated before testing.
+ SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+ SwViewShell* pViewShell
+ = pTextDoc->GetDocShell()->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
+ CPPUNIT_ASSERT(pViewShell);
+ pViewShell->Reformat();
+
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+ // There is only a single shrunk line 1, without breaking the last word
+ // before the last text portion "i"
+
+ // This ends in "dolorsi" (not "dolors", as before)
+ assertXPath(
+ pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout[1]"_ostr, "portion"_ostr,
+ u"Quis pretium semper. Proin luctus orci a neque venenatis, quis commodo dolorsi"_ustr);
+
+ // no second line (there was a second line with the text portion "i").
+ assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout"_ostr, 1);
+}
+
CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf162109)
{
createSwDoc("tdf162109.fodt");
diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx
index f0867a2557a6..a9bd581a63ad 100644
--- a/sw/source/core/text/guess.cxx
+++ b/sw/source/core/text/guess.cxx
@@ -194,7 +194,9 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
{
static constexpr OUStringLiteral STR_BLANK = u" ";
sal_Int16 nSpaceWidth = rInf.GetTextSize(STR_BLANK).Width();
- nLineWidth += nSpacesInLine * (nSpaceWidth/0.8 - nSpaceWidth);
+ SwTwips nExtraSpace = nSpacesInLine * (nSpaceWidth/0.8 - nSpaceWidth);
+ nLineWidth += nExtraSpace;
+ rInf.SetExtraSpace(nExtraSpace);
}
if ( rInf.GetLen() < nMaxLen )
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index 38f51bb74468..8471cf8282d5 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -220,6 +220,7 @@ SwTextSizeInfo::SwTextSizeInfo()
, m_bForbiddenChars(false)
, m_bSnapToGrid(false)
, m_nDirection(0)
+, m_nExtraSpace(0)
{}
SwTextSizeInfo::SwTextSizeInfo( const SwTextSizeInfo &rNew )
@@ -250,7 +251,8 @@ SwTextSizeInfo::SwTextSizeInfo( const SwTextSizeInfo &rNew )
m_bScriptSpace( rNew.HasScriptSpace() ),
m_bForbiddenChars( rNew.HasForbiddenChars() ),
m_bSnapToGrid( rNew.SnapToGrid() ),
- m_nDirection( rNew.GetDirection() )
+ m_nDirection( rNew.GetDirection() ),
+ m_nExtraSpace( rNew.GetExtraSpace() )
{
#if OSL_DEBUG_LEVEL > 0
ChkOutDev( *this );
@@ -262,6 +264,7 @@ void SwTextSizeInfo::CtorInitTextSizeInfo( OutputDevice* pRenderContext, SwTextF
{
m_pKanaComp = nullptr;
m_nKanaIdx = 0;
+ m_nExtraSpace = 0;
m_pFrame = pFrame;
CtorInitTextInfo( m_pFrame );
SwDoc const& rDoc(m_pFrame->GetDoc());
@@ -362,7 +365,8 @@ SwTextSizeInfo::SwTextSizeInfo( const SwTextSizeInfo &rNew, const OUString* pTex
m_bScriptSpace( rNew.HasScriptSpace() ),
m_bForbiddenChars( rNew.HasForbiddenChars() ),
m_bSnapToGrid( rNew.SnapToGrid() ),
- m_nDirection( rNew.GetDirection() )
+ m_nDirection( rNew.GetDirection() ),
+ m_nExtraSpace( rNew.GetExtraSpace() )
{
#if OSL_DEBUG_LEVEL > 0
ChkOutDev( *this );
diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx
index 461d7a1261eb..8576ed5c8707 100644
--- a/sw/source/core/text/inftxt.hxx
+++ b/sw/source/core/text/inftxt.hxx
@@ -175,6 +175,7 @@ protected:
bool m_bForbiddenChars : 1; // Forbidden start/endline characters
bool m_bSnapToGrid : 1; // paragraph snaps to grid
sal_uInt8 m_nDirection : 2; // writing direction: 0/90/180/270 degree
+ SwTwips m_nExtraSpace; // extra space before shrinking = nSpacesInLine * (nSpaceWidth/0.8 - nSpaceWidth)
protected:
void CtorInitTextSizeInfo( OutputDevice* pRenderContext, SwTextFrame *pFrame,
@@ -300,6 +301,10 @@ public:
bool HasHint(TextFrameIndex nPos) const;
+ // extra space before shrinking = nSpacesInLine * (nSpaceWidth/0.8 - nSpaceWidth)
+ void SetExtraSpace(SwTwips nVal) { m_nExtraSpace = nVal; }
+ SwTwips GetExtraSpace() const { return m_nExtraSpace; }
+
// If Kana Compression is enabled, a minimum and maximum portion width
// is calculated. We format lines with minimal size and share remaining
// space among compressed kanas.
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 3317ca05725e..752aadb5ffb8 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -2123,6 +2123,7 @@ TextFrameIndex SwTextFormatter::FormatLine(TextFrameIndex const nStartPos)
}
}
GetInfo().ResetMaxWidthDiff();
+ GetInfo().SetExtraSpace(0);
// delete old rest
if ( GetInfo().GetRest() )
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index 4c71e5da2c29..b310ee706cb5 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -514,7 +514,7 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
bool SwTextPortion::Format( SwTextFormatInfo &rInf )
{
// GetLineWidth() takes care of DocumentSettingId::TAB_OVER_MARGIN.
- if( rInf.GetLineWidth() < 0 || (!GetLen() && !InExpGrp()) )
+ if( rInf.GetLineWidth() + rInf.GetExtraSpace() < 0 || (!GetLen() && !InExpGrp()) )
{
Height( 0 );
Width( 0 );