QFusionStyle: don't lose precision when drawing a progress bar

When qreal is float, it cannot represent all values an int can take,
so we may lose precision in the expression

  qreal(value) - minimum

as opposed to the exact result

  qint64(value) - minimum'

For lack of trying, I do not know of a value where this would change
the resulting 'progressBarWidth' value, but better be safe than sorry,
and use the 64-bit integer expression instead of floating-point.

Found while reviewing integer arithmetic in QProgressBar as part of
the fix for QTBUG-57857.

Change-Id: I0240c143bb75af6986910489b34042ce9b3a8caa
Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
Marc Mutz 2017-01-05 08:10:53 +01:00
parent 894cd9bcfc
commit 555a0f3c51

View File

@ -1352,10 +1352,11 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
}
int maxWidth = rect.width();
int minWidth = 0;
qreal progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar
int progressBarWidth = (progress - bar->minimum) * qreal(maxWidth) / qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum);
int width = indeterminate ? maxWidth : qMax(minWidth, progressBarWidth);
const auto progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar
const auto totalSteps = qMax(Q_INT64_C(1), qint64(bar->maximum) - bar->minimum);
const auto progressSteps = qint64(progress) - bar->minimum;
const auto progressBarWidth = progressSteps * maxWidth / totalSteps;
int width = indeterminate ? maxWidth : progressBarWidth;
bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical;
if (inverted)
@ -1450,8 +1451,9 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
inverted = bar->invertedAppearance;
if (vertical)
rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
const int progressIndicatorPos = (bar->progress - qreal(bar->minimum)) * rect.width() /
qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum);
const auto totalSteps = qMax(Q_INT64_C(1), qint64(bar->maximum) - bar->minimum);
const auto progressSteps = qint64(bar->progress) - bar->minimum;
const auto progressIndicatorPos = progressSteps * rect.width() / totalSteps;
if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width())
leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height());
if (vertical)