sw/source/core/text/portxt.cxx |   69 +++++++++++++++++++++--------------------
 1 file changed, 36 insertions(+), 33 deletions(-)

New commits:
commit 3fdbc6083336f84ed7fa55fb0ec3fd0288382967
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Tue Jun 11 20:23:22 2024 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Thu Jun 13 11:43:17 2024 +0200

    tdf#160170 sw: fix overshrunk justified lines at hyphenation
    
    Smart justify uses 2 SwTextGuess::Guess() calls to break a
    line, but using the same SwTextGuess object resulted overshrunk
    lines, if the first call resulted hyphenation, because of the
    bad state of the object for the second call. If we need a
    second call, now instantiate a new object for it.
    
    Regression from commit 36bfc86e27fa03ee16f87819549ab126c5a68cac
    "tdf#119908 tdf#158776 sw smart justify: shrink only spaces".
    
    Note: the reported test document was already fixed by
    commit f050103c3324d878b310f37429ea3580a8230905
    "stale hyphenation data after skipping blanks".
    
    Change-Id: I478407dc7650206d3feb72d5b89e78b1194590c1
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168693
    Reviewed-by: László Németh <nem...@numbertext.org>
    Tested-by: Jenkins
    (cherry picked from commit ca540209a8c20a2734f180d4706d5153bdf64523)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168724

diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index 8dcf75dc0019..b82936d4c1d4 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -301,14 +301,14 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
         return bFull;
     }
 
-    SwTextGuess aGuess;
-    bool bFull = !aGuess.Guess( *this, rInf, Height() );
+    std::unique_ptr<SwTextGuess> pGuess(new SwTextGuess());
+    bool bFull = !pGuess->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 &&
-         aGuess.BreakPos() != TextFrameIndex(COMPLETE_STRING) &&
+         pGuess->BreakPos() != TextFrameIndex(COMPLETE_STRING) &&
          rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
                     DocumentSettingId::JUSTIFY_LINES_WITH_SHRINKING) &&
          // tdf#158436 avoid shrinking at underflow, e.g. no-break space after 
a
@@ -316,7 +316,7 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
          !rInf.IsUnderflow() )
     {
         sal_Int32 nSpacesInLine(0);
-        for (sal_Int32 i = sal_Int32(rInf.GetLineStart()); i < 
sal_Int32(aGuess.BreakPos()); ++i)
+        for (sal_Int32 i = sal_Int32(rInf.GetLineStart()); i < 
sal_Int32(pGuess->BreakPos()); ++i)
         {
             sal_Unicode cChar = rInf.GetText()[i];
             if ( cChar == CH_BLANK )
@@ -329,16 +329,19 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
         // TODO: handle the case, if the line contains extra amount of spaces
         if (
              // no automatic hyphenation
-             !aGuess.HyphWord().is() &&
+             !pGuess->HyphWord().is() &&
              // no hyphenation at soft hyphen
-             aGuess.BreakPos() < TextFrameIndex(rInf.GetText().getLength()) &&
-             rInf.GetText()[sal_Int32(aGuess.BreakPos())] != CHAR_SOFTHYPHEN )
+             pGuess->BreakPos() < TextFrameIndex(rInf.GetText().getLength()) &&
+             rInf.GetText()[sal_Int32(pGuess->BreakPos())] != CHAR_SOFTHYPHEN )
         {
             ++nSpacesInLine;
         }
 
         if ( nSpacesInLine > 0 )
-            bFull = !aGuess.Guess( *this, rInf, Height(), nSpacesInLine );
+        {
+            pGuess.reset(new SwTextGuess());
+            bFull = !pGuess->Guess( *this, rInf, Height(), nSpacesInLine );
+        }
     }
 
     // these are the possible cases:
@@ -357,8 +360,8 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
     // case A: line not yet full
     if ( !bFull )
     {
-        Width( aGuess.BreakWidth() );
-        ExtraBlankWidth(aGuess.ExtraBlankWidth());
+        Width( pGuess->BreakWidth() );
+        ExtraBlankWidth(pGuess->ExtraBlankWidth());
         // Caution!
         if( !InExpGrp() || InFieldGrp() )
             SetLen( rInf.GetLen() );
@@ -374,22 +377,22 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
             new SwKernPortion( *this, nKern );
     }
     // special case: hanging portion
-    else if( aGuess.GetHangingPortion() )
+    else if( pGuess->GetHangingPortion() )
     {
-        Width( aGuess.BreakWidth() );
-        SetLen( aGuess.BreakPos() - rInf.GetIdx() );
-        aGuess.GetHangingPortion()->SetAscent( GetAscent() );
-        Insert( aGuess.ReleaseHangingPortion() );
+        Width( pGuess->BreakWidth() );
+        SetLen( pGuess->BreakPos() - rInf.GetIdx() );
+        pGuess->GetHangingPortion()->SetAscent( GetAscent() );
+        Insert( pGuess->ReleaseHangingPortion() );
     }
     // breakPos >= index
-    else if (aGuess.BreakPos() >= rInf.GetIdx() && aGuess.BreakPos() != 
TextFrameIndex(COMPLETE_STRING))
+    else if (pGuess->BreakPos() >= rInf.GetIdx() && pGuess->BreakPos() != 
TextFrameIndex(COMPLETE_STRING))
     {
         // case B1
-        if( aGuess.HyphWord().is() && aGuess.BreakPos() > rInf.GetLineStart()
-            && ( aGuess.BreakPos() > rInf.GetIdx() ||
+        if( pGuess->HyphWord().is() && pGuess->BreakPos() > rInf.GetLineStart()
+            && ( pGuess->BreakPos() > rInf.GetIdx() ||
                ( rInf.GetLast() && ! rInf.GetLast()->IsFlyPortion() ) ) )
         {
-            CreateHyphen( rInf, aGuess );
+            CreateHyphen( rInf, *pGuess );
             if ( rInf.GetFly() )
                 rInf.GetRoot()->SetMidHyph( true );
             else
@@ -410,14 +413,14 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
                     
rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT)
 &&
                     rInf.GetLast()->InTabGrp() &&
                     rInf.GetLineStart() + rInf.GetLast()->GetLen() < 
rInf.GetIdx() &&
-                    aGuess.BreakPos() == rInf.GetIdx()  &&
+                    pGuess->BreakPos() == rInf.GetIdx()  &&
                     CH_BLANK != rInf.GetChar( rInf.GetIdx() ) &&
                     CH_FULL_BLANK != rInf.GetChar( rInf.GetIdx() ) &&
                     CH_SIX_PER_EM != rInf.GetChar( rInf.GetIdx() ) ) )
             BreakUnderflow( rInf );
         // case B2
         else if( rInf.GetIdx() > rInf.GetLineStart() ||
-                 aGuess.BreakPos() > rInf.GetIdx() ||
+                 pGuess->BreakPos() > rInf.GetIdx() ||
                  // this is weird: during formatting the follow of a field
                  // the values rInf.GetIdx and rInf.GetLineStart are replaced
                  // IsFakeLineStart indicates GetIdx > GetLineStart
@@ -431,36 +434,36 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
                           ! rInf.GetLast()->IsErgoSumPortion() &&
                           
lcl_HasContent(*static_cast<SwFieldPortion*>(rInf.GetLast()),rInf ) ) ) ) )
         {
-            Width( aGuess.BreakWidth() );
+            Width( pGuess->BreakWidth() );
 
-            SetLen( aGuess.BreakPos() - rInf.GetIdx() );
+            SetLen( pGuess->BreakPos() - rInf.GetIdx() );
 
-            OSL_ENSURE( aGuess.BreakStart() >= aGuess.FieldDiff(),
+            OSL_ENSURE( pGuess->BreakStart() >= pGuess->FieldDiff(),
                     "Trouble with expanded field portions during line break" );
-            TextFrameIndex const nRealStart = aGuess.BreakStart() - 
aGuess.FieldDiff();
-            if( aGuess.BreakPos() < nRealStart && !InExpGrp() )
+            TextFrameIndex const nRealStart = pGuess->BreakStart() - 
pGuess->FieldDiff();
+            if( pGuess->BreakPos() < nRealStart && !InExpGrp() )
             {
                 SwHolePortion *pNew = new SwHolePortion( *this );
-                pNew->SetLen( nRealStart - aGuess.BreakPos() );
+                pNew->SetLen( nRealStart - pGuess->BreakPos() );
                 pNew->Width(0);
-                pNew->ExtraBlankWidth( aGuess.ExtraBlankWidth() );
+                pNew->ExtraBlankWidth( pGuess->ExtraBlankWidth() );
                 Insert( pNew );
 
                 // UAX #14 Unicode Line Breaking Algorithm Non-tailorable Line 
breaking rule LB6:
                 // https://www.unicode.org/reports/tr14/#LB6 Do not break 
before hard line breaks
-                if (auto ch = rInf.GetChar(aGuess.BreakStart()); !ch || ch == 
CH_BREAK)
+                if (auto ch = rInf.GetChar(pGuess->BreakStart()); !ch || ch == 
CH_BREAK)
                     bFull = false; // Keep following SwBreakPortion / para 
break in the same line
             }
         }
         else    // case C2, last exit
-            BreakCut( rInf, aGuess );
+            BreakCut( rInf, *pGuess );
     }
     // breakPos < index or no breakpos at all
     else
     {
         bool bFirstPor = rInf.GetLineStart() == rInf.GetIdx();
-        if (aGuess.BreakPos() != TextFrameIndex(COMPLETE_STRING) &&
-            aGuess.BreakPos() != rInf.GetLineStart() &&
+        if (pGuess->BreakPos() != TextFrameIndex(COMPLETE_STRING) &&
+            pGuess->BreakPos() != rInf.GetLineStart() &&
             ( !bFirstPor || rInf.GetFly() || rInf.GetLast()->IsFlyPortion() ||
               rInf.IsFirstMulti() ) &&
             ( !rInf.GetLast()->IsBlankPortion() ||
@@ -470,7 +473,7 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
         }
         else
              // case C2, last exit
-            BreakCut(rInf, aGuess);
+            BreakCut(rInf, *pGuess);
     }
 
     return bFull;

Reply via email to