diff options
author | Jonathan Clark <jonathan@libreoffice.org> | 2024-08-06 06:01:57 -0600 |
---|---|---|
committer | Jonathan Clark <jonathan@libreoffice.org> | 2024-08-06 21:57:10 +0200 |
commit | 981c5780da8ec6b6878de58909b7cc7e736ad33a (patch) | |
tree | 1aa339fca2afc4a338ef3c79d58075ef85edd0eb /sc | |
parent | 166f0bcae39d4b6842f7578afb28fff3cf950d68 (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.cxx | 16 |
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(); |