sw/qa/extras/layout/layout3.cxx |    6 ++++++
 sw/source/core/text/guess.cxx   |   15 ++++++---------
 sw/source/core/text/guess.hxx   |    2 +-
 sw/source/core/text/portxt.cxx  |   25 ++++++++++++++++++++++++-
 4 files changed, 37 insertions(+), 11 deletions(-)

New commits:
commit 8d247e3ad47e0b828437abb019e1573dbb1c05b1
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Tue Dec 19 11:58:40 2023 +0100
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Thu Dec 28 13:49:48 2023 +0100

    tdf#119908 tdf#158776 sw smart justify: shrink only spaces
    
    For interoperability, only shrink spaces up to 20%,
    not the lines up to 2%.
    
    Follow-up to commit 20cbe88ce5610fd8ee302e5780a4c0821ddb3db4
    "tdf#119908 tdf#158419 sw smart justify: fix cursor position"
    and commit 7d08767b890e723cd502b1c61d250924f695eb98
    "tdf#130088 tdf#119908 smart justify: fix DOCX line count + compat opt."
    
    Change-Id: Idb43161cb5a57c3412abd3f0eb266c6afbe5363c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160988
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit 36bfc86e27fa03ee16f87819549ab126c5a68cac)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161325
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx
index ea2c3a52d24e..ec7d740cf74f 100644
--- a/sw/qa/extras/layout/layout3.cxx
+++ b/sw/qa/extras/layout/layout3.cxx
@@ -236,6 +236,12 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf158333)
                 "portion"_ostr,
                 // This was "...et ", not "...et magnis "
                 "consequat arcu ut diam tempor luctus. Cum sociis natoque 
penatibus et magnis ");
+
+    // tdf#158776 don't shrink line 11 of paragraph 4
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[4]/SwParaPortion/SwLineLayout[11]"_ostr,
+                "portion"_ostr,
+                // This was "...quis curcus ", not "...quis "
+                "venenatis, quis commodo dolor posuere. Curabitur dignissim 
sapien quis ");
 }
 
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf158419)
diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx
index 37a2147d0987..6123ad1b6767 100644
--- a/sw/source/core/text/guess.cxx
+++ b/sw/source/core/text/guess.cxx
@@ -50,7 +50,7 @@ bool IsBlank(sal_Unicode ch) { return ch == CH_BLANK || ch == 
CH_FULL_BLANK || c
 // returns true if no line break has to be performed
 // otherwise possible break or hyphenation position is determined
 bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
-                            const sal_uInt16 nPorHeight )
+                            const sal_uInt16 nPorHeight, sal_Int32 
nSpacesInLine )
 {
     m_nCutPos = rInf.GetIdx();
 
@@ -80,15 +80,12 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, 
SwTextFormatInfo &rInf,
 
     const SvxAdjust& rAdjust = 
rInf.GetTextFrame()->GetTextNodeForParaProps()->GetSwAttrSet().GetAdjust().GetAdjust();
 
-    // allow shrinking, i.e. more text in justified lines, depending on the 
justification algorithm
-    if ( rAdjust == SvxAdjust::Block && 
rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
-                    DocumentSettingId::JUSTIFY_LINES_WITH_SHRINKING) &&
-         // tdf#158436 avoid shrinking at underflow, e.g. no-break space
-         // after a very short word resulted endless loop
-         !rInf.IsUnderflow() )
+    // allow up to 20% shrinking of the spaces
+    if ( nSpacesInLine )
     {
-        // allow up to 2% shrinking of the line
-        nLineWidth = nLineWidth / 0.98 + rInf.X() / 0.98 - rInf.X();
+        static constexpr OUStringLiteral STR_BLANK = u" ";
+        sal_Int16 nSpaceWidth = rInf.GetTextSize(STR_BLANK).Width();
+        nLineWidth += nSpacesInLine * (nSpaceWidth/0.8 - nSpaceWidth);
     }
 
     // tdf#104668 space chars at the end should be cut if the compatibility 
option is enabled
diff --git a/sw/source/core/text/guess.hxx b/sw/source/core/text/guess.hxx
index f83c7e280ae4..5a7a9ac1cfa2 100644
--- a/sw/source/core/text/guess.hxx
+++ b/sw/source/core/text/guess.hxx
@@ -46,7 +46,7 @@ public:
 
     // true, if current portion still fits to current line
     bool Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
-                    const sal_uInt16 nHeight );
+                    const sal_uInt16 nHeight, sal_Int32 nSpacesInLine = 0 );
     bool AlternativeSpelling( const SwTextFormatInfo &rInf, const 
TextFrameIndex nPos );
 
     SwHangingPortion* GetHangingPortion() const { return m_pHanging.get(); }
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index 9631fc232dc3..0d3960c1bcbc 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -302,7 +302,30 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
     }
 
     SwTextGuess aGuess;
-    const bool bFull = !aGuess.Guess( *this, rInf, Height() );
+    bool bFull = !aGuess.Guess( *this, rInf, Height() );
+
+    // tdf#158776 for the last full text portion, call Guess() again to allow 
more text in the
+    // adjusted line by shrinking spaces using the know space count from the 
first Guess() call
+    const SvxAdjust& rAdjust = 
rInf.GetTextFrame()->GetTextNodeForParaProps()->GetSwAttrSet().GetAdjust().GetAdjust();
+    if ( bFull && rAdjust == SvxAdjust::Block &&
+         rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
+                    DocumentSettingId::JUSTIFY_LINES_WITH_SHRINKING) &&
+         // tdf#158436 avoid shrinking at underflow, e.g. no-break space after 
a
+         // very short word resulted endless loop
+         !rInf.IsUnderflow() )
+    {
+        sal_Int32 nSpacesInLine(0);
+        for (sal_Int32 i = sal_Int32(rInf.GetLineStart()); i < 
sal_Int32(aGuess.BreakPos()); ++i)
+        {
+            sal_Unicode cChar = rInf.GetText()[i];
+            if ( cChar == CH_BLANK )
+                ++nSpacesInLine;
+        }
+
+        // call with an extra space: shrinking can result a new word in the 
line
+        // and a new space before that, which is also a shrank space
+        bFull = !aGuess.Guess( *this, rInf, Height(), nSpacesInLine + 1 );
+    }
 
     // these are the possible cases:
     // A Portion fits to current line

Reply via email to