summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorJonathan Clark <jonathan@libreoffice.org>2024-08-06 06:01:57 -0600
committerJonathan Clark <jonathan@libreoffice.org>2024-08-06 21:57:10 +0200
commit981c5780da8ec6b6878de58909b7cc7e736ad33a (patch)
tree1aa339fca2afc4a338ef3c79d58075ef85edd0eb /sc
parent166f0bcae39d4b6842f7578afb28fff3cf950d68 (diff)
tdf#160786 sc: Fix repeat char format code inaccuracy
Number format codes allow arbitrary repeat characters. These repeat characters are inserted while formatting numbers to pad strings to the width of the containing cell. For example, this is used in some default format codes to left-align currency symbols with right-aligned digits. Previously, Calc determined the number of repeat characters to insert based on the assumption that the pixel width of a string containing N of the repeat character would be N times the pixel width of a string containing 1 of them. This is not a safe assumption. This change updates the algorithm to instead look at the average width of a repeat character when used in context as part of a padding string. This approach is still not entirely correct - it doesn't account for ligatures around the padding sequence, for example - but in practice it is a reasonable compromise between cost and accuracy. Change-Id: I240cf38ec0376ee2d2896e7a7da6760a374b3034 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171548 Tested-by: Jenkins Reviewed-by: Jonathan Clark <jonathan@libreoffice.org>
Diffstat (limited to 'sc')
-rw-r--r--sc/source/ui/view/output2.cxx16
1 files changed, 13 insertions, 3 deletions
diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx
index 1a8d1356a4a6..cab30c900136 100644
--- a/sc/source/ui/view/output2.cxx
+++ b/sc/source/ui/view/output2.cxx
@@ -573,8 +573,17 @@ void ScDrawStringsVars::RepeatToFill( tools::Long nColWidth )
if ( nRepeatPos == -1 || nRepeatPos > aString.getLength() )
return;
- tools::Long nCharWidth = GetFmtTextWidth(OUString(nRepeatChar));
+ // Measuring a string containing a single copy of the repeat char is inaccurate.
+ // To increase accuracy, start with a representative sample of a padding sequence.
+ constexpr sal_Int32 nSampleSize = 20;
+ OUStringBuffer aFill(nSampleSize);
+ comphelper::string::padToLength(aFill, nSampleSize, nRepeatChar);
+ tools::Long nSampleWidth = GetFmtTextWidth(aFill.makeStringAndClear());
+ double nAvgCharWidth = static_cast<double>(nSampleWidth) / static_cast<double>(nSampleSize);
+
+ // Intentionally truncate to round toward zero
+ auto nCharWidth = static_cast<tools::Long>(nAvgCharWidth);
if ( nCharWidth < 1 || (bPixelToLogic && nCharWidth < pOutput->mpRefDevice->PixelToLogic(Size(1,0)).Width()) )
return;
@@ -590,8 +599,9 @@ void ScDrawStringsVars::RepeatToFill( tools::Long nColWidth )
if ( nSpaceToFill <= nCharWidth )
return;
- sal_Int32 nCharsToInsert = nSpaceToFill / nCharWidth;
- OUStringBuffer aFill(nCharsToInsert);
+ // Intentionally truncate to round toward zero
+ auto nCharsToInsert = static_cast<sal_Int32>(static_cast<double>(nSpaceToFill) / nAvgCharWidth);
+ aFill.ensureCapacity(nCharsToInsert);
comphelper::string::padToLength(aFill, nCharsToInsert, nRepeatChar);
aString = aString.replaceAt( nRepeatPos, 0, aFill );
TextChanged();