sw/inc/swscanner.hxx | 4 ++++ sw/source/core/txtnode/txtedt.cxx | 25 +++++++++++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-)
New commits: commit 50e722923d4efaadac7a11ec523501cebd341cb1 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Fri Mar 14 15:49:32 2025 +0200 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Fri Mar 14 18:01:51 2025 +0100 cool#1125 Reduce cost of spell checking in writer Loading a new CharClass for each NextWord() call can add up. Change-Id: Ie15f2adcd4c603074320b49d5c0276f558aab3e9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182920 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/sw/inc/swscanner.hxx b/sw/inc/swscanner.hxx index 88433bfe4bb1..8a26085bc40f 100644 --- a/sw/inc/swscanner.hxx +++ b/sw/inc/swscanner.hxx @@ -22,8 +22,10 @@ #include <i18nlangtag/lang.h> #include "modeltoviewhelper.hxx" +#include <unotools/charclass.hxx> #include <functional> +#include <optional> class SwTextNode; @@ -43,6 +45,8 @@ class SwScanner sal_Int32 m_nBegin; sal_Int32 m_nLength; sal_Int32 m_nOverriddenDashCount; + // caches the CharClass for m_aCurrentLang, which can be expensive to repeatedly retrieve + std::optional<CharClass> moCharClass; LanguageType m_aCurrentLang; sal_uInt16 m_nWordType; bool m_bClip; diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx index df0582e1f058..87ef9fa945e1 100644 --- a/sw/source/core/txtnode/txtedt.cxx +++ b/sw/source/core/txtnode/txtedt.cxx @@ -35,7 +35,6 @@ #include <osl/diagnose.h> #include <officecfg/Office/Writer.hxx> #include <unotools/transliterationwrapper.hxx> -#include <unotools/charclass.hxx> #include <sal/log.hxx> #include <swmodule.hxx> #include <splargs.hxx> @@ -778,15 +777,21 @@ SwScanner::SwScanner(std::function<LanguageType(sal_Int32, sal_Int32, bool)> aGe assert(m_aPreDashReplacementText.getLength() == m_aText.getLength()); + LanguageType aNewLang; if ( m_pLanguage ) { - m_aCurrentLang = *m_pLanguage; + aNewLang = *m_pLanguage; } else { ModelToViewHelper::ModelPosition aModelBeginPos = m_ModelToView.ConvertToModelPosition( m_nBegin ); - m_aCurrentLang = m_pGetLangOfChar(aModelBeginPos.mnPos, 0, true); + aNewLang = m_pGetLangOfChar(aModelBeginPos.mnPos, 0, true); + } + if (m_aCurrentLang != aNewLang) + { + m_aCurrentLang = aNewLang; + moCharClass.reset(); } } @@ -855,8 +860,6 @@ bool SwScanner::NextWord() m_nBegin = m_nBegin + m_nLength; Boundary aBound; - std::optional<CharClass> xLocalCharClass; - while ( true ) { // skip non-letter characters: @@ -869,13 +872,19 @@ bool SwScanner::NextWord() const sal_uInt16 nNextScriptType = g_pBreakIt->GetBreakIter()->getScriptType( m_aText, m_nBegin ); ModelToViewHelper::ModelPosition aModelBeginPos = m_ModelToView.ConvertToModelPosition( m_nBegin ); - m_aCurrentLang = m_pGetLangOfChar(aModelBeginPos.mnPos, nNextScriptType, false); + LanguageType aNewLang = m_pGetLangOfChar(aModelBeginPos.mnPos, nNextScriptType, false); + if (aNewLang != m_aCurrentLang) + { + m_aCurrentLang = aNewLang; + moCharClass.reset(); + } } if ( m_nWordType != i18n::WordType::WORD_COUNT ) { - xLocalCharClass.emplace(LanguageTag( g_pBreakIt->GetLocale( m_aCurrentLang ) )); - if ( xLocalCharClass->isLetterNumeric(OUString(m_aText[m_nBegin])) ) + if (!moCharClass) + moCharClass.emplace(LanguageTag( g_pBreakIt->GetLocale( m_aCurrentLang ) )); + if ( moCharClass->isLetterNumeric(OUString(m_aText[m_nBegin])) ) break; } else