Kaydet (Commit) 0d0119ef authored tarafından Stephan Bergmann's avatar Stephan Bergmann Kaydeden (comit) Miklos Vajna

In FitToAcutalSize, keep SwColumn's width >= left + right borders

Given SwColumn::m_nWish is documented as "Desired width, borders included."
(sw/inc/fmtclds.hxx), it appears that the invariant

  GetWishWidth() >= GetLeft() + GetRight()

should always hold for SwColumn instances.

However, during UITest_writer_tests4's test_tdf113284 loading of
sw/qa/uitest/writer_tests/data/tdf113284.odt, it appears that some five-column
table is created for which initially all SwColumns'

  GetWishWidth() = 13107
  GetLeft() = 144 (except for first SwColumn, where it's 0)
  GetRight() = 144 (except for last SwColumn, where it's 0)

and later FitToActualSize is called reducing each SwColunn to

  GetWishWidth() = 286

so that for most SwColumns (except first and last), GetLeft() + GetRight() = 288
would exceed GetWishWidth().  And then (still during loading of the test's
document), SwFormatCol::CalcPrtColWidth (sw/source/core/layout/atrfrm.cxx) is
called for such a problematic SwColumn, trying to subtract from its
GetWishWidth() (the result of SwFormatCol::CalcColWidth) both GetLeft() and
GetRight(), and store that into sal_uInt16 nRet.  Which triggers Clang's
-fsanitize=implicit-signed-integer-truncation "runtime error: implicit
conversion from type 'int' of value -2 (32-bit, signed) to type 'sal_uInt16'
(aka 'unsigned short') changed the value to 65534 (16-bit, unsigned)".

So make sure that FitToAcutalSize upholds that presumed SwColumns invariant,
shrinking the borders as necessary.

Change-Id: I3f6fc07e65a0fc5d5f58c99f1dcdea4467b825f0
Reviewed-on: https://gerrit.libreoffice.org/68463
Tested-by: Jenkins
Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.com>
üst 8ae5a988
......@@ -17,6 +17,10 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <sal/config.h>
#include <algorithm>
#include <hintids.hxx>
#include <editeng/lrspitem.hxx>
#include <osl/diagnose.h>
......@@ -34,7 +38,28 @@ void FitToActualSize(SwFormatCol& rCol, sal_uInt16 nWidth)
for(sal_uInt16 i = 0; i < nCount; ++i)
{
const sal_uInt16 nTmp = rCol.CalcColWidth(i, nWidth);
rCol.GetColumns()[i].SetWishWidth(nTmp);
auto & col = rCol.GetColumns()[i];
col.SetWishWidth(nTmp);
// If necessary, shrink borders (as equally as possible) to keep up the invariant that
// GetWishWidth() >= GetLeft() + GetRight():
sal_uInt32 const borders = col.GetLeft() + col.GetRight();
if (borders > nTmp)
{
auto const shrink = borders - nTmp;
auto const half = shrink / 2; // rounds down
if (col.GetLeft() < col.GetRight())
{
auto const shrinkLeft = std::min(sal_uInt32(col.GetLeft()), half);
col.SetLeft(col.GetLeft() - shrinkLeft);
col.SetRight(col.GetRight() - (shrink - shrinkLeft));
}
else
{
auto const shrinkRight = std::min(sal_uInt32(col.GetRight()), half);
col.SetLeft(col.GetLeft() - (shrink - shrinkRight));
col.SetRight(col.GetRight() - shrinkRight);
}
}
}
rCol.SetWishWidth(nWidth);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment