Skip to content

Commit b0f9480

Browse files
AW1534tresfrubiefawn
authored
Fix SVG Scaling; Allow SVGs to be rendered at sizes other than their natural size. (LMMS#7769)
Allow embed.cpp to load SVG assets at screen DPI by leveraging QPixmap::setDevicePixelRatio --------- Co-authored-by: Tres Finocchiaro <tres.finocchiaro@gmail.com> Co-authored-by: Fawn <rubiefawn@gmail.com>
1 parent 2cd4810 commit b0f9480

File tree

3 files changed

+59
-6
lines changed

3 files changed

+59
-6
lines changed

src/gui/embed.cpp

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,74 @@
2424

2525
#include "embed.h"
2626

27-
#include <QDebug>
2827
#include <QDir>
28+
#include <QGuiApplication>
2929
#include <QImageReader>
30+
#include <QPainter>
3031
#include <QPixmapCache>
3132
#include <QResource>
33+
#include <QScreen>
34+
#include <QSvgRenderer>
3235

3336
namespace lmms::embed {
3437

3538
namespace {
3639

40+
// QPixmapCache and HiDPI compatible SVG-->QPixmap wrapper
41+
auto loadSvgPixmap(const QString& resourceName, int width, int height) -> QPixmap
42+
{
43+
// QFile requires the file extension to be present, unlike QImageReader
44+
QString fileName = resourceName;
45+
if (!fileName.endsWith(".svg", Qt::CaseInsensitive)) { fileName += ".svg"; }
46+
47+
QFile file(fileName);
48+
if (!file.open(QIODevice::ReadOnly))
49+
{
50+
qWarning() << "Failed to open resource for SVG: " << resourceName;
51+
return QPixmap{1, 1};
52+
}
53+
54+
QSvgRenderer renderer(file.readAll());
55+
if (!renderer.isValid())
56+
{
57+
qWarning() << "Error loading SVG file: " << resourceName;
58+
return QPixmap{1, 1};
59+
}
60+
61+
// Get the default size of the SVG (without scaling)
62+
QSize svgSize = renderer.defaultSize();
63+
64+
// If width/height are provided, use them
65+
if (width > 0 && height > 0) { svgSize.scale(width, height, Qt::IgnoreAspectRatio); }
66+
67+
// Scale the svg
68+
qreal devicePixelRatio = QGuiApplication::primaryScreen()->devicePixelRatio();
69+
svgSize *= devicePixelRatio;
70+
71+
QImage image(svgSize, QImage::Format_ARGB32);
72+
image.fill(Qt::transparent);
73+
QPainter painter(&image);
74+
renderer.render(&painter);
75+
painter.end();
76+
77+
auto pixmap = QPixmap::fromImage(image);
78+
pixmap.setDevicePixelRatio(devicePixelRatio);
79+
80+
return pixmap;
81+
}
82+
3783
auto loadPixmap(const QString& name, int width, int height, const char* const* xpm) -> QPixmap
3884
{
3985
if (xpm) { return QPixmap{xpm}; }
4086

4187
const auto resourceName = QDir::isAbsolutePath(name) ? name : "artwork:" + name;
4288
auto reader = QImageReader{resourceName};
89+
90+
if (reader.format().toLower() == "svg")
91+
{
92+
return loadSvgPixmap(resourceName, width, height);
93+
}
94+
4395
if (width > 0 && height > 0) { reader.setScaledSize(QSize{width, height}); }
4496

4597
const auto pixmap = QPixmap::fromImageReader(&reader);

src/gui/tracks/TrackOperationsWidget.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,17 +108,16 @@ TrackOperationsWidget::TrackOperationsWidget( TrackView * parent ) :
108108
const auto activePixmap = embed::getIconPixmap(activeGraphic);
109109
const auto inactivePixmap = embed::getIconPixmap(inactiveGraphic);
110110

111-
auto necessarySize = activePixmap.size().expandedTo(inactivePixmap.size());
112-
113111
auto wrapperWidget = new QWidget(parent);
114-
wrapperWidget->setFixedSize(necessarySize);
115112

116113
auto button = new PixmapButton(wrapperWidget, toolTip);
117114
button->setCheckable(true);
118115
button->setActiveGraphic(activePixmap);
119116
button->setInactiveGraphic(inactivePixmap);
120117
button->setToolTip(toolTip);
121118

119+
wrapperWidget->setFixedSize(button->minimumSizeHint());
120+
122121
pixmapButton = button;
123122

124123
return wrapperWidget;

src/gui/widgets/PixmapButton.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ void PixmapButton::mouseDoubleClickEvent( QMouseEvent * _me )
107107
void PixmapButton::setActiveGraphic( const QPixmap & _pm )
108108
{
109109
m_activePixmap = _pm;
110-
resize( m_activePixmap.width(), m_activePixmap.height() );
110+
resize(m_activePixmap.size() / m_activePixmap.devicePixelRatio());
111111
}
112112

113113

@@ -129,7 +129,9 @@ QSize PixmapButton::sizeHint() const
129129

130130
QSize PixmapButton::minimumSizeHint() const
131131
{
132-
return m_activePixmap.size().expandedTo(m_inactivePixmap.size());
132+
const auto activeSize = m_activePixmap.size() / m_activePixmap.devicePixelRatio();
133+
const auto inactiveSize = m_inactivePixmap.size() / m_inactivePixmap.devicePixelRatio();
134+
return activeSize.expandedTo(inactiveSize);
133135
}
134136

135137
bool PixmapButton::isActive() const

0 commit comments

Comments
 (0)