QCommonStyle: Fix painting arrows when size is even

Rework the painting code to not use floating point numbers and make sure
the tip of the arrow is painted with one or two points (depending on the
size is odd or even) so the arrow is always symmetric. Therefore also no
anti-aliasing is needed. Sadly the dpr scaling and also
QPainter::drawPolygon() screw things up a little bit with such small
sizes, therefore do the dpr handling by ourself to get nice results.

Pick-to: 6.7
Fixes: QTBUG-124554
Task-number: QTBUG-114539
Change-Id: I8ab8c2ce3ceb90af5d7c3a0dfeec7f7445e92a4d
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
bb10
Christian Ehrlicher 2024-04-28 13:48:39 +02:00
parent ccbff2c08b
commit bbff35a343
1 changed files with 31 additions and 25 deletions

View File

@ -761,56 +761,62 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
% HexString<uint>(pe),
opt, QSize(size, size), dpr);
if (!QPixmapCache::find(pixmapName, &pixmap)) {
const qreal border = dpr * (size / 5.);
const qreal sqsize = dpr * size;
pixmap = QPixmap(QSize(size, size));
pixmap.fill(Qt::transparent);
QPainter imagePainter(&pixmap);
// dpr scaling does not work well on such small pixel sizes, do it on our own
const int border = 1 * dpr;
const int sizeDpr = size * dpr;
int width = sizeDpr - 2 * border - 1;
int height = width / 2;
const int add = ((width & 1) == 1);
if (pe == PE_IndicatorArrowRight || pe == PE_IndicatorArrowLeft)
std::swap(width, height);
pixmap = styleCachePixmap(QSize(sizeDpr, sizeDpr), 1);
QPolygonF poly;
std::array<QPointF, 4> poly;
switch (pe) {
case PE_IndicatorArrowUp:
poly = {QPointF(border, sqsize / 2), QPointF(sqsize / 2, border), QPointF(sqsize - border, sqsize / 2)};
poly = {QPointF(0, height), QPointF(width, height),
QPointF(width / 2 + add, 0), QPointF(width / 2, 0)};
break;
case PE_IndicatorArrowDown:
poly = {QPointF(border, sqsize / 2), QPointF(sqsize / 2, sqsize - border), QPointF(sqsize - border, sqsize / 2)};
poly = {QPointF(0, 0), QPointF(width, 0),
QPointF(width / 2 + add, height), QPointF(width / 2, height)};
break;
case PE_IndicatorArrowRight:
poly = {QPointF(sqsize - border, sqsize / 2), QPointF(sqsize / 2, border), QPointF(sqsize / 2, sqsize - border)};
poly = {QPointF(0, 0), QPointF(0, height),
QPointF(width, height / 2 + add), QPointF(width, height / 2)};
break;
case PE_IndicatorArrowLeft:
poly = {QPointF(border, sqsize / 2), QPointF(sqsize / 2, border), QPointF(sqsize / 2, sqsize - border)};
poly = {QPointF(width, 0), QPointF(width, height),
QPointF(0, height / 2 + add), QPointF(0, height / 2)};
break;
default:
break;
}
int bsx = 0;
int bsy = 0;
QPainter imagePainter(&pixmap);
imagePainter.translate((sizeDpr - width) / 2, (sizeDpr - height) / 2);
if (opt->state & State_Sunken) {
bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget);
bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget);
const auto bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget);
const auto bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget);
imagePainter.translate(bsx, bsy);
}
const QPointF boundsCenter = poly.boundingRect().center();
const qreal sx = sqsize / 2 - boundsCenter.x();
const qreal sy = sqsize / 2 - boundsCenter.y();
imagePainter.translate(sx + bsx, sy + bsy);
imagePainter.setPen(opt->palette.buttonText().color());
imagePainter.setBrush(opt->palette.buttonText());
if (!(opt->state & State_Enabled)) {
imagePainter.translate(1, 1);
const int ofs = qRound(1 * dpr);
imagePainter.translate(ofs, ofs);
imagePainter.setBrush(opt->palette.light().color());
imagePainter.setPen(opt->palette.light().color());
imagePainter.drawPolygon(poly);
imagePainter.translate(-1, -1);
imagePainter.drawPolygon(poly.data(), int(poly.size()));
imagePainter.drawPoints(poly.data(), int(poly.size()));
imagePainter.translate(-ofs, -ofs);
imagePainter.setBrush(opt->palette.mid().color());
imagePainter.setPen(opt->palette.mid().color());
}
imagePainter.drawPolygon(poly);
imagePainter.drawPolygon(poly.data(), int(poly.size()));
// sometimes the corners are not drawn by drawPolygon for unknown reaons, so re-draw them again
imagePainter.drawPoints(poly.data(), int(poly.size()));
imagePainter.end();
pixmap.setDevicePixelRatio(dpr);
QPixmapCache::insert(pixmapName, pixmap);