tdf#162830 sc LayoutStrings: use decimal size to fit repeat into width

Using the rounded integer width of a single character
and using that to determine how many times to repeat it in a give space
is bound to result in disaster.
Instead, determine an approximation of the real size of the string.

This is just layout stuff - no idea how to capture it in a unit test.

Change-Id: Ie0cbc891d986357a1037b1476cb1cd4c9601e876
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/210439
Reviewed-by: Justin Luth <jluth@mail.com>
Tested-by: Jenkins
This commit is contained in:
Justin Luth
2026-09-03 01:55:01 +02:00
parent d68e181ef9
commit bf588c5d9a
+21 -5
View File
@@ -1899,17 +1899,33 @@ void ScOutputData::LayoutStringsImpl(bool const bPixelToLogic, RowInfo* const pT
if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip )
{
tools::Long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin;
tools::Long nRepeatSize = aVars.GetTextSize().Width(); // without margin
double fRepeatSize = aVars.GetTextSize().Width(); // without margin
const OUString& aCellStr = aVars.GetString();
// Measuring a string containing a single copy of a short repeat string is inaccurate.
// To increase accuracy, start with a representative sample of the repeated sequence.
constexpr sal_Int32 nSampleSize = 20;
const size_t nLen = aCellStr.getLength();
if (nLen && nLen < nSampleSize)
{
OUStringBuffer aFill(aCellStr);
aFill.ensureCapacity(nSampleSize);
while (aFill.getLength() < nSampleSize)
aFill.append(aCellStr);
fRepeatSize
= aVars.GetFmtTextWidth(aFill.copy(0, nSampleSize).makeStringAndClear());
fRepeatSize = fRepeatSize * nLen / nSampleSize;
}
// When formatting for the printer, the text sizes don't always add up.
// Round down (too few repetitions) rather than exceeding the cell size then:
if ( pFmtDevice != mpRefDevice )
++nRepeatSize;
if ( nRepeatSize > 0 )
++fRepeatSize;
if (fRepeatSize > 0)
{
tools::Long nRepeatCount = nAvailable / nRepeatSize;
const tools::Long nRepeatCount = nAvailable / fRepeatSize;
if ( nRepeatCount > 1 )
{
OUString aCellStr = aVars.GetString();
OUStringBuffer aRepeated(aCellStr);
for ( tools::Long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
aRepeated.append(aCellStr);