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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user