Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/widgets/dstyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Q_DECLARE_FLAGS(Corners, Corner)

void drawShadow(QPainter *pa, const QRect &rect, qreal xRadius, qreal yRadius, const QColor &sc, qreal radius, const QPoint &offset);
void drawShadow(QPainter *pa, const QRect &rect, const QPainterPath &path, const QColor &sc, int radius, const QPoint &offset);
void drawInsetShadow(QPainter *pa, const QRect &rect, qreal xRadius, qreal yRadius, const QColor &sc, qreal radius, const QPoint &offset);
void drawRoundedRect(QPainter *pa, const QRect &rect, qreal xRadius, qreal yRadius, Corners corners, Qt::SizeMode mode = Qt::AbsoluteSize);
void drawFork(QPainter *pa, const QRectF &rect, const QColor &color, int width = 2);
void drawMark(QPainter *pa, const QRectF &rect, const QColor &boxInside, const QColor &boxOutside, const int penWidth, const int outLineLeng = 2);
Expand Down
55 changes: 55 additions & 0 deletions src/widgets/dstyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,62 @@
pa->drawPixmap(shadow_rect, shadow);
}

void drawInsetShadow(QPainter *pa, const QRect &rect, qreal xRadius, qreal yRadius, const QColor &sc, qreal radius, const QPoint &offset)

Check warning on line 395 in src/widgets/dstyle.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'drawInsetShadow' is never used.
{
if (radius <= 0 || rect.isNull())
return;

qreal scale = pa->paintEngine()->paintDevice()->devicePixelRatioF();
QSize size = rect.size() * scale;
xRadius *= scale;
yRadius *= scale;
radius *= scale;
QPoint scaledOffset(offset.x() * scale, offset.y() * scale);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The offset is multiplied by the device-pixel ratio and then truncated when constructing the QPoint, so a logical offset of 1 pixel becomes 1 physical pixel rather than 1.5 pixels on a 1.5x display. The inset shadow therefore has an incorrect offset on fractional-DPR devices.

Triggers: When the painter targets a device with a fractional device-pixel ratio and offset is nonzero.

Suggested fix: Use a QPointF for the scaled offset, or round the scaled components explicitly before drawing.

Suggested change
QPoint scaledOffset(offset.x() * scale, offset.y() * scale);
QPointF scaledOffset(offset.x() * scale, offset.y() * scale);


// Build an opaque image, then cut out a rounded-rect hole shifted by
// 'offset'. After blurring, the hole edges fade inward, producing an
// inset shadow. Positive offset.y() makes the shadow stronger at the
// top edge; negative at the bottom.
QImage shadow_base(size, QImage::Format_ARGB32_Premultiplied);
shadow_base.fill(Qt::black);

QPainter holePainter(&shadow_base);
holePainter.setRenderHint(QPainter::Antialiasing, true);
holePainter.setPen(Qt::NoPen);
holePainter.setCompositionMode(QPainter::CompositionMode_Clear);
holePainter.setBrush(Qt::transparent);
QRectF holeRect = QRectF(shadow_base.rect()).translated(scaledOffset);
holeRect = holeRect.marginsRemoved(QMarginsF(radius, radius, radius, radius));
holePainter.drawRoundedRect(holeRect, xRadius, yRadius);
holePainter.end();

// Blur the alpha channel so the hole edges become a soft gradient.
QImage blurred(size, QImage::Format_ARGB32_Premultiplied);
blurred.fill(0);
QPainter blurPainter(&blurred);
qt_blurImage(&blurPainter, shadow_base, radius, false, true);
blurPainter.end();

// Replace the placeholder black with the actual shadow color.
QPainter colorPainter(&blurred);
colorPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
colorPainter.fillRect(blurred.rect(), sc);
colorPainter.end();

blurred.setDevicePixelRatio(scale);

// Clip to the rounded-rect shape so the opaque outer area is hidden;
// only the inward-fading shadow at the edges is visible.
pa->save();
pa->setRenderHint(QPainter::Antialiasing, true);
QPainterPath clipPath;
clipPath.addRoundedRect(rect, xRadius / scale, yRadius / scale);
pa->setClipPath(clipPath);
pa->drawImage(rect.topLeft(), blurred);
pa->restore();
}

void drawFork(QPainter *pa, const QRectF &rect, const QColor &color, int width)

Check warning on line 450 in src/widgets/dstyle.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'drawFork' is never used.
{
QPen pen;
pen.setWidth(width);
Expand Down
Loading