Consolidate calls to GetLocalizedChar into one helper function
The three places that call GetLocalizedChar were all functions that were
doing the same thing, ie, localizing the digits in a string. Instead of
having three separate copies of this similar code, this patch stops
exporting GetLocalizedChar and instead exports a utility function that
operates on a string.
One of the three versions of the code avoided allocating a new string if
nothing changes. This new consolidated helper uses the same approach
so that the other two places can take advantage of this very likely
optimisation.
The main motivation to do this was to avoid truncating the sal_UCS4
returned by GetLocalizedChar into a sal_Unicode. The consolidated
implementation adds the converted characters with appendUtf32 instead so
that if GetLocalizedChar ever returns characters outside of the BMP then
it would work. In practice this doesn’t currently happen so it’s not an
actual problem. However the commit below makes the compiler warn when
sal_UCS4 is truncated, so this patch fixes a truncation that was marked
as a TODO in that commit.
commit 82f055e5cb
Author: Noel Grandin <noel.grandin@collabora.co.uk>
Date: Tue Nov 4 10:12:18 2025 +0200
new loplugin:narrow
Change-Id: I628a29520a0896cd0f4c7c2ff131ac763e07925b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193460
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
committed by
Noel Grandin
parent
8278f03f9e
commit
117d9624a3
@@ -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<sal_Unicode>(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());
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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<sal_Unicode>(GetLocalizedChar(cChar, eDigitLang));
|
||||
}
|
||||
return aBuf.makeStringAndClear();
|
||||
}
|
||||
|
||||
// Either sets the digit mode at the output device
|
||||
void ImpEditEngine::ImplInitDigitMode(OutputDevice& rOutDev, LanguageType eCurLang)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 ),
|
||||
|
||||
@@ -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<OUStringBuffer> 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<sal_Unicode>(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
|
||||
|
||||
Reference in New Issue
Block a user