sw/qa/core/text/frmform.cxx     |    4 +---
 sw/source/core/inc/drawfont.hxx |    6 +++++-
 sw/source/core/text/inftxt.cxx  |    2 +-
 sw/source/core/text/inftxt.hxx  |    6 ++++--
 sw/source/core/text/itradj.cxx  |   13 ++++++++++++-
 sw/source/core/text/porlay.hxx  |    7 ++++++-
 sw/source/core/text/portxt.cxx  |    7 +------
 7 files changed, 30 insertions(+), 15 deletions(-)

New commits:
commit 17eaebee279772b6062ae3448012133897fc71bb
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Wed Nov 15 23:31:12 2023 +0100
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Thu Nov 16 16:21:06 2023 +0100

    tdf#119908 sw smart justify: fix justification by shrinking
    
    Shrink the exceeding lines by shrinking the spaces
    between the words.
    
    Because the negative spacing values are used
    for the extra space between the characters in the main
    data structure of the justified line layout, and not for
    the space between the words, like the positive values,
    the negative space values for shrinking are stored over
    LONG_MAX/2 as absolute values to avoid of bigger changes
    of the data structure before designing a better
    justification algorithm, where it's possible to mix
    different methods for the more visible text layout.
    
    Note: the text cursor doesn't follow the new word
    positions yet.
    
    Follow-up to commit 7d08767b890e723cd502b1c61d250924f695eb98
    "tdf#130088 tdf#119908 smart justify: fix DOCX line count + compat opt."
    
    Change-Id: I9a63b5a93d6bce230e963ebc88ea2d0f9aa8fffb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159511
    Reviewed-by: László Németh <nem...@numbertext.org>
    Tested-by: László Németh <nem...@numbertext.org>

diff --git a/sw/qa/core/text/frmform.cxx b/sw/qa/core/text/frmform.cxx
index b321fca51cee..3d43bde6aa9c 100644
--- a/sw/qa/core/text/frmform.cxx
+++ b/sw/qa/core/text/frmform.cxx
@@ -63,9 +63,7 @@ CPPUNIT_TEST_FIXTURE(Test, testFloattableNegativeVertOffset)
     CPPUNIT_ASSERT_LESS(pPara2->getFrameArea().Top(), rFlyRect.Bottom());
 }
 
-// FIXME: because breaking the lines at the right place, this test
-// became obsolete: proposed fix is to modify compatibilityMode to "14"
-// in the DOCX test file to use the old justification algorithm
+// FIXME: because breaking the lines at the right place, test document became 
obsolete
 #if 0
 CPPUNIT_TEST_FIXTURE(Test, testFloattableAvoidManipOfst)
 {
diff --git a/sw/source/core/inc/drawfont.hxx b/sw/source/core/inc/drawfont.hxx
index 3d58f5fcd09d..fe6a44264759 100644
--- a/sw/source/core/inc/drawfont.hxx
+++ b/sw/source/core/inc/drawfont.hxx
@@ -544,7 +544,11 @@ public:
         }
         else
         {
-            m_nSpace = nNew;
+            // negative space (shrinking) stored over LONG_MAX/2
+            if ( nNew < LONG_MAX/2 )
+                m_nSpace = nNew;
+            else
+                m_nSpace = LONG_MAX/2 - nNew;
             m_nCharacterSpacing = 0;
         }
 #ifdef DBG_UTIL
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index 82bbf9d879bf..129234c8a4cf 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -634,7 +634,7 @@ void SwTextPaintInfo::DrawText_( const OUString &rText, 
const SwLinePortion &rPo
     aDrawInf.SetUnderFnt( m_pUnderFnt );
 
     const tools::Long nSpaceAdd = ( rPor.IsBlankPortion() || 
rPor.IsDropPortion() ||
-                             rPor.InNumberGrp() ) ? 0 : GetSpaceAdd();
+                             rPor.InNumberGrp() ) ? 0 : 
GetSpaceAdd(/*bShrink=*/true);
     if ( nSpaceAdd )
     {
         TextFrameIndex nCharCnt(0);
diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx
index 62cca26ac08f..f2f6d146136e 100644
--- a/sw/source/core/text/inftxt.hxx
+++ b/sw/source/core/text/inftxt.hxx
@@ -443,8 +443,10 @@ public:
     void SetSpaceIdx( sal_uInt16 nNew ) { m_nSpaceIdx = nNew; }
     void IncSpaceIdx() { ++m_nSpaceIdx; }
     void RemoveFirstSpaceAdd() { m_pSpaceAdd->erase( m_pSpaceAdd->begin() ); }
-    tools::Long GetSpaceAdd() const
-        { return ( m_pSpaceAdd && m_nSpaceIdx < m_pSpaceAdd->size() )
+    tools::Long GetSpaceAdd( bool bShrink = false ) const
+        { return ( m_pSpaceAdd && m_nSpaceIdx < m_pSpaceAdd->size() &&
+                   // get shrink data only if asked explicitly, otherwise zero 
it
+                   ( bShrink || (*m_pSpaceAdd)[m_nSpaceIdx] < LONG_MAX/2 ) )
                    ? (*m_pSpaceAdd)[m_nSpaceIdx] : 0; }
 
     void SetpSpaceAdd( std::vector<tools::Long>* pNew ){ m_pSpaceAdd = pNew; }
diff --git a/sw/source/core/text/itradj.cxx b/sw/source/core/text/itradj.cxx
index b72a8d59f5f7..4dcaf03df1f8 100644
--- a/sw/source/core/text/itradj.cxx
+++ b/sw/source/core/text/itradj.cxx
@@ -290,6 +290,8 @@ void SwTextAdjuster::CalcNewBlock( SwLineLayout *pCurrent,
     bool bDoNotJustifyTab = false;
 
     SwLinePortion *pPos = pCurrent->GetNextPortion();
+    // calculate real text width for shrinking
+    tools::Long nBreakWidth = 0;
 
     while( pPos )
     {
@@ -367,6 +369,11 @@ void SwTextAdjuster::CalcNewBlock( SwLineLayout *pCurrent,
                 if( nGluePortion )
                 {
                     tools::Long nSpaceAdd = nGluePortionWidth / 
sal_Int32(nGluePortion);
+                    // shrink, if portions exceed the line width
+                    tools::Long nSpaceSub = ( nBreakWidth > pCurrent->Width() )
+                        ? (nBreakWidth - pCurrent->Width()) * 
SPACING_PRECISION_FACTOR /
+                                sal_Int32(nGluePortion) + LONG_MAX/2
+                        : 0;
 
                     // i60594
                     if( rSI.CountKashida() && !bSkipKashida )
@@ -382,7 +389,7 @@ void SwTextAdjuster::CalcNewBlock( SwLineLayout *pCurrent,
                         }
                     }
 
-                    pCurrent->SetLLSpaceAdd( nSpaceAdd , nSpaceIdx );
+                    pCurrent->SetLLSpaceAdd( nSpaceSub ? nSpaceSub : 
nSpaceAdd, nSpaceIdx );
                     pPos->Width( 
static_cast<SwGluePortion*>(pPos)->GetFixWidth() );
                 }
                 else if (IsOneBlock() && nCharCnt > TextFrameIndex(1))
@@ -399,6 +406,10 @@ void SwTextAdjuster::CalcNewBlock( SwLineLayout *pCurrent,
             else
                 ++nGluePortion;
         }
+        else
+        {
+            nBreakWidth += pPos->Width();
+        }
         GetInfo().SetIdx( GetInfo().GetIdx() + pPos->GetLen() );
         if ( pPos == pStopAt )
         {
diff --git a/sw/source/core/text/porlay.hxx b/sw/source/core/text/porlay.hxx
index 3b07b7016118..e9e5f3d3f261 100644
--- a/sw/source/core/text/porlay.hxx
+++ b/sw/source/core/text/porlay.hxx
@@ -192,7 +192,12 @@ public:
         else
             (*m_pLLSpaceAdd)[ nIdx ] = nNew;
     }
-    tools::Long GetLLSpaceAdd( sal_uInt16 nIdx ) { return (*m_pLLSpaceAdd)[ 
nIdx ]; }
+    tools::Long GetLLSpaceAdd( sal_uInt16 nIdx, bool bShrink = false )
+    {
+        // get shrink data only if asked explicitly, otherwise zero it
+        return ( bShrink || (*m_pLLSpaceAdd)[ nIdx ] < LONG_MAX/2 )
+            ? (*m_pLLSpaceAdd)[ nIdx ] : 0;
+    }
     void RemoveFirstLLSpaceAdd() { m_pLLSpaceAdd->erase( 
m_pLLSpaceAdd->begin() ); }
     std::vector<tools::Long>* GetpLLSpaceAdd() const { return 
m_pLLSpaceAdd.get(); }
 
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index 99595c1a71f7..1e2f8d1823d0 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -394,12 +394,7 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
                           ! rInf.GetLast()->IsErgoSumPortion() &&
                           
lcl_HasContent(*static_cast<SwFieldPortion*>(rInf.GetLast()),rInf ) ) ) ) )
         {
-            // GetLineWidth() takes care of DocumentSettingId::TAB_OVER_MARGIN.
-            if (aGuess.BreakWidth() <= rInf.GetLineWidth())
-                Width( aGuess.BreakWidth() );
-            else
-                // this actually should not happen
-                Width( sal_uInt16(rInf.Width() - rInf.X()) );
+            Width( aGuess.BreakWidth() );
 
             SetLen( aGuess.BreakPos() - rInf.GetIdx() );
 

Reply via email to