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() );