diff --git a/cppcanvas/source/mtfrenderer/implrenderer.cxx b/cppcanvas/source/mtfrenderer/implrenderer.cxx index d11f9cdada40..e7b04397507b 100644 --- a/cppcanvas/source/mtfrenderer/implrenderer.cxx +++ b/cppcanvas/source/mtfrenderer/implrenderer.cxx @@ -215,20 +215,6 @@ namespace return Bitmap( aSolid, aMask ); } - - OUString convertToLocalizedNumerals(std::u16string_view rStr, - LanguageType eTextLanguage) - { - OUStringBuffer aBuf(rStr); - for (sal_Int32 i = 0; i < aBuf.getLength(); ++i) - { - sal_Unicode nChar = aBuf[i]; - if (nChar >= '0' && nChar <= '9') - // TODO: are the localized digit surrogates? - aBuf[i] = static_cast(GetLocalizedChar(nChar, eTextLanguage)); - } - return aBuf.makeStringAndClear(); - } } namespace cppcanvas::internal @@ -2438,7 +2424,7 @@ namespace cppcanvas::internal OUString sText = pAct->GetText(); if (rVDev.GetDigitLanguage()) - sText = convertToLocalizedNumerals(sText, rVDev.GetDigitLanguage()); + sText = LocalizeDigitsInString(sText, rVDev.GetDigitLanguage()); const sal_Int32 nLen = std::min(pAct->GetLen(), pAct->GetText().getLength() - pAct->GetIndex()); @@ -2460,7 +2446,7 @@ namespace cppcanvas::internal OUString sText = pAct->GetText(); if (rVDev.GetDigitLanguage()) - sText = convertToLocalizedNumerals(sText, rVDev.GetDigitLanguage()); + sText = LocalizeDigitsInString(sText, rVDev.GetDigitLanguage()); const sal_Int32 nLen = std::min(pAct->GetLen(), pAct->GetText().getLength() - pAct->GetIndex()); @@ -2540,7 +2526,7 @@ namespace cppcanvas::internal OUString sText = pAct->GetText(); if (rVDev.GetDigitLanguage()) - sText = convertToLocalizedNumerals(sText, rVDev.GetDigitLanguage()); + sText = LocalizeDigitsInString(sText, rVDev.GetDigitLanguage()); const sal_Int32 nLen = std::min(pAct->GetLen(), pAct->GetText().getLength() - pAct->GetIndex()); diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx index 338145db8973..72eadc1b79ac 100644 --- a/editeng/source/editeng/impedit.hxx +++ b/editeng/source/editeng/impedit.hxx @@ -771,7 +771,6 @@ private: void ImplInitLayoutMode(OutputDevice& rOutDev, sal_Int32 nPara, sal_Int32 nIndex); static LanguageType ImplCalcDigitLang(LanguageType eCurLang); static void ImplInitDigitMode(OutputDevice& rOutDev, LanguageType eLang); - static OUString convertDigits(std::u16string_view rString, sal_Int32 nStt, sal_Int32 nLen, LanguageType eDigitLang); EditPaM ReadText( SvStream& rInput, EditSelection aSel ); EditPaM ReadRTF( SvStream& rInput, EditSelection aSel ); diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index 1298eb314b91..000d959c7b89 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -3906,8 +3906,9 @@ void ImpEditEngine::StripAllPortions( OutputDevice& rOutDev, tools::Rectangle aC const Color aTextLineColor(rOutDev.GetTextLineColor()); // Unicode code points conversion according to ctl text numeral setting - aText = convertDigits(aText, nTextStart, nTextLen, - ImplCalcDigitLang(aTmpFont.GetLanguage())); + aText = LocalizeDigitsInString(aText, + ImplCalcDigitLang(aTmpFont.GetLanguage()), + nTextStart, nTextLen); // StripPortions() data callback const DrawPortionInfo aInfo( @@ -4668,19 +4669,6 @@ LanguageType ImpEditEngine::ImplCalcDigitLang(LanguageType eCurLang) return eLang; } -OUString ImpEditEngine::convertDigits(std::u16string_view rString, sal_Int32 nStt, sal_Int32 nLen, LanguageType eDigitLang) -{ - OUStringBuffer aBuf(rString); - for (sal_Int32 nIdx = nStt, nEnd = nStt + nLen; nIdx < nEnd; ++nIdx) - { - sal_Unicode cChar = aBuf[nIdx]; - if (cChar >= '0' && cChar <= '9') - // TODO: are the localized digit surrogates? - aBuf[nIdx] = static_cast(GetLocalizedChar(cChar, eDigitLang)); - } - return aBuf.makeStringAndClear(); -} - // Either sets the digit mode at the output device void ImpEditEngine::ImplInitDigitMode(OutputDevice& rOutDev, LanguageType eCurLang) { diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx index ef908f61931b..43cb3f9535b0 100644 --- a/include/vcl/svapp.hxx +++ b/include/vcl/svapp.hxx @@ -84,7 +84,13 @@ namespace com::sun::star::awt { class XWindow; } -VCL_DLLPUBLIC sal_UCS4 GetLocalizedChar( sal_UCS4, LanguageType ); +VCL_DLLPUBLIC OUString LocalizeDigitsInString( const OUString&, LanguageType, + sal_Int32 nStart, sal_Int32& nLen ); +inline OUString LocalizeDigitsInString( const OUString& sStr, LanguageType eTextLanguage ) +{ + sal_Int32 nLen = sStr.getLength(); + return LocalizeDigitsInString(sStr, eTextLanguage, 0, nLen); +} enum class SystemWindowFlags { NOAUTOMODE = 0x0001, diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index aa9dca1d6e06..67b52fba8d39 100644 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -47,6 +47,8 @@ #define GF_FONTMASK 0xF0000000 #define GF_FONTSHIFT 28 +namespace +{ sal_UCS4 GetLocalizedChar( sal_UCS4 nChar, LanguageType eLang ) { @@ -121,6 +123,51 @@ sal_UCS4 GetLocalizedChar( sal_UCS4 nChar, LanguageType eLang ) return nChar; } +} + +OUString LocalizeDigitsInString( const OUString& sStr, LanguageType eTextLanguage, + sal_Int32 nStart, sal_Int32& nLen ) +{ + sal_Int32 nextPos, nEnd = nStart + nLen; + + for (sal_Int32 i = nStart; i < nEnd; i = nextPos) + { + nextPos = i; + sal_uInt32 nChar = sStr.iterateCodePoints(&nextPos); + + sal_UCS4 nReplacementChar = GetLocalizedChar(nChar, eTextLanguage); + + // The first time we encounter a character that needs to change we’ll make a copy of the + // string so we can return a new modified one + if (nReplacementChar != nChar) + { + // The new string is very likely to have the same length as the old one + OUStringBuffer xTmpStr(sStr.getLength()); + xTmpStr.append(sStr.subView(0, i)); + xTmpStr.appendUtf32(nReplacementChar); + + // Convert the remainder of the range + for (i = nextPos; i < nEnd;) + { + nReplacementChar = GetLocalizedChar(sStr.iterateCodePoints(&i), eTextLanguage); + xTmpStr.appendUtf32(nReplacementChar); + } + + // Add the rest of the string outside of the range + xTmpStr.append(sStr.subView(nEnd)); + + // The length of the string might have changed if GetLocalizedChar converts between BMP + // and surrogate pairs + nLen += xTmpStr.getLength() - sStr.getLength(); + + return xTmpStr.makeStringAndClear(); + } + } + + // Nothing changed so we can just return the original string + return sStr; +} + SalLayout::SalLayout() : mnMinCharPos( -1 ), mnEndCharPos( -1 ), diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index ba190b047cfe..4b1afddcfc14 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -994,29 +994,9 @@ vcl::text::ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr, if( meTextLanguage ) //TODO: (mnTextLayoutMode & vcl::text::ComplexTextLayoutFlags::SubstituteDigits) { - // disable character localization when no digits used - const sal_Unicode* pBase = rStr.getStr(); - const sal_Unicode* pStr = pBase + nMinIndex; - const sal_Unicode* pEnd = pBase + nEndIndex; - std::optional xTmpStr; - for( ; pStr < pEnd; ++pStr ) - { - // TODO: are there non-digit localizations? - if( (*pStr >= '0') && (*pStr <= '9') ) - { - // translate characters to local preference - sal_UCS4 cChar = GetLocalizedChar( *pStr, meTextLanguage ); - if( cChar != *pStr ) - { - if (!xTmpStr) - xTmpStr = OUStringBuffer(rStr); - // TODO: are the localized digit surrogates? - (*xTmpStr)[pStr - pBase] = static_cast(cChar); - } - } - } - if (xTmpStr) - rStr = (*xTmpStr).makeStringAndClear(); + sal_Int32 nSubstringLen = nEndIndex - nMinIndex; + rStr = LocalizeDigitsInString(rStr, meTextLanguage, nMinIndex, nSubstringLen); + nEndIndex = nMinIndex + nSubstringLen; } // right align for RTL text, DRAWPOS_REVERSED, RTL window style