From 99c7cf2816b2d0016832552dbe6c55456ade42e0 Mon Sep 17 00:00:00 2001 From: Jonathan Clark Date: Fri, 4 Oct 2024 11:50:25 -0600 Subject: crashtesting: fix font-dependent infinite loop in kashida justification Commit c3c29d31d77ff93aa50634cfd51c62d12dc0f6ec (tdf#140767 Implemented Syriac justification) indirectly introduced a font-dependent infinite loop in Writer layout by relaxing some restrictions on kashida candidate positions. The infinite loop was found in tdf97806-2.odt. This change fixes an underlying logic bug in Writer, which caused Writer to attempt to apply kashida justification to non-Arabic/Syriac CTL scripts. This change also reintroduces some of the previously-lifted restrictions on kashida candidate positions. Change-Id: I783bf327f4ef0f1f6a032f0d3dddbcfd60a026fa Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174503 Tested-by: Jenkins Reviewed-by: Jonathan Clark --- sw/source/core/text/itradj.cxx | 15 ++++++++------- sw/source/core/text/porlay.cxx | 23 ++++++++++++++--------- 2 files changed, 22 insertions(+), 16 deletions(-) (limited to 'sw') diff --git a/sw/source/core/text/itradj.cxx b/sw/source/core/text/itradj.cxx index c072025e7a96..be004457b407 100644 --- a/sw/source/core/text/itradj.cxx +++ b/sw/source/core/text/itradj.cxx @@ -167,10 +167,11 @@ static bool lcl_CheckKashidaPositions(SwScriptInfo& rSI, SwTextSizeInfo& rInf, S const OUString& rWord = aScanner.GetWord(); // Fetch the set of valid positions from VCL, where possible - aValidPositions.clear(); if (SwScriptInfo::IsKashidaScriptText(rInf.GetText(), TextFrameIndex{ aScanner.GetBegin() }, TextFrameIndex{ aScanner.GetLen() })) { + aValidPositions.clear(); + rItr.SeekAndChgAttrIter(TextFrameIndex{ aScanner.GetBegin() }, rInf.GetRefDev()); vcl::text::ComplexTextLayoutFlags nOldLayout = rInf.GetRefDev()->GetLayoutMode(); @@ -179,13 +180,13 @@ static bool lcl_CheckKashidaPositions(SwScriptInfo& rSI, SwTextSizeInfo& rInf, S rInf.GetRefDev()->GetWordKashidaPositions(rWord, &aValidPositions); rInf.GetRefDev()->SetLayoutMode(nOldLayout); - } - auto stKashidaPos = i18nutil::GetWordKashidaPosition(rWord, aValidPositions); - if (stKashidaPos.has_value()) - { - TextFrameIndex nNewKashidaPos{ aScanner.GetBegin() + stKashidaPos->nIndex }; - aNewKashidaPositions.push_back(nNewKashidaPos); + auto stKashidaPos = i18nutil::GetWordKashidaPosition(rWord, aValidPositions); + if (stKashidaPos.has_value()) + { + TextFrameIndex nNewKashidaPos{ aScanner.GetBegin() + stKashidaPos->nIndex }; + aNewKashidaPositions.push_back(nNewKashidaPos); + } } } diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx index d433c3bbd3cd..39a260ac0ef8 100644 --- a/sw/source/core/text/porlay.cxx +++ b/sw/source/core/text/porlay.cxx @@ -1525,16 +1525,21 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode, // the search has to be performed on a per word base while ( aScanner.NextWord() ) { - const OUString& rWord = aScanner.GetWord(); - auto stKashidaPos = i18nutil::GetWordKashidaPosition(rWord); - - if (stKashidaPos.has_value()) + if (SwScriptInfo::IsKashidaScriptText(rText, TextFrameIndex{ aScanner.GetBegin() }, + TextFrameIndex{ aScanner.GetLen() })) { - // Only populate kashida positions for the invalidated tail - TextFrameIndex nNewKashidaPos{aScanner.GetBegin() + stKashidaPos->nIndex}; - if(nNewKashidaPos >= nLastKashida) { - m_Kashida.insert(m_Kashida.begin() + nCntKash, nNewKashidaPos); - nCntKash++; + const OUString& rWord = aScanner.GetWord(); + auto stKashidaPos = i18nutil::GetWordKashidaPosition(rWord); + + if (stKashidaPos.has_value()) + { + // Only populate kashida positions for the invalidated tail + TextFrameIndex nNewKashidaPos{ aScanner.GetBegin() + stKashidaPos->nIndex }; + if (nNewKashidaPos >= nLastKashida) + { + m_Kashida.insert(m_Kashida.begin() + nCntKash, nNewKashidaPos); + nCntKash++; + } } } } // end of kashida search -- cgit