Fix SVG Scaling; Allow SVGs to be rendered at sizes other than their natural size. (#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>
This commit is contained in:
@@ -24,22 +24,74 @@
|
||||
|
||||
#include "embed.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QGuiApplication>
|
||||
#include <QImageReader>
|
||||
#include <QPainter>
|
||||
#include <QPixmapCache>
|
||||
#include <QResource>
|
||||
#include <QScreen>
|
||||
#include <QSvgRenderer>
|
||||
|
||||
namespace lmms::embed {
|
||||
|
||||
namespace {
|
||||
|
||||
// QPixmapCache and HiDPI compatible SVG-->QPixmap wrapper
|
||||
auto loadSvgPixmap(const QString& resourceName, int width, int height) -> QPixmap
|
||||
{
|
||||
// QFile requires the file extension to be present, unlike QImageReader
|
||||
QString fileName = resourceName;
|
||||
if (!fileName.endsWith(".svg", Qt::CaseInsensitive)) { fileName += ".svg"; }
|
||||
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
qWarning() << "Failed to open resource for SVG: " << resourceName;
|
||||
return QPixmap{1, 1};
|
||||
}
|
||||
|
||||
QSvgRenderer renderer(file.readAll());
|
||||
if (!renderer.isValid())
|
||||
{
|
||||
qWarning() << "Error loading SVG file: " << resourceName;
|
||||
return QPixmap{1, 1};
|
||||
}
|
||||
|
||||
// Get the default size of the SVG (without scaling)
|
||||
QSize svgSize = renderer.defaultSize();
|
||||
|
||||
// If width/height are provided, use them
|
||||
if (width > 0 && height > 0) { svgSize.scale(width, height, Qt::IgnoreAspectRatio); }
|
||||
|
||||
// Scale the svg
|
||||
qreal devicePixelRatio = QGuiApplication::primaryScreen()->devicePixelRatio();
|
||||
svgSize *= devicePixelRatio;
|
||||
|
||||
QImage image(svgSize, QImage::Format_ARGB32);
|
||||
image.fill(Qt::transparent);
|
||||
QPainter painter(&image);
|
||||
renderer.render(&painter);
|
||||
painter.end();
|
||||
|
||||
auto pixmap = QPixmap::fromImage(image);
|
||||
pixmap.setDevicePixelRatio(devicePixelRatio);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
auto loadPixmap(const QString& name, int width, int height, const char* const* xpm) -> QPixmap
|
||||
{
|
||||
if (xpm) { return QPixmap{xpm}; }
|
||||
|
||||
const auto resourceName = QDir::isAbsolutePath(name) ? name : "artwork:" + name;
|
||||
auto reader = QImageReader{resourceName};
|
||||
|
||||
if (reader.format().toLower() == "svg")
|
||||
{
|
||||
return loadSvgPixmap(resourceName, width, height);
|
||||
}
|
||||
|
||||
if (width > 0 && height > 0) { reader.setScaledSize(QSize{width, height}); }
|
||||
|
||||
const auto pixmap = QPixmap::fromImageReader(&reader);
|
||||
|
||||
@@ -108,10 +108,7 @@ TrackOperationsWidget::TrackOperationsWidget( TrackView * parent ) :
|
||||
const auto activePixmap = embed::getIconPixmap(activeGraphic);
|
||||
const auto inactivePixmap = embed::getIconPixmap(inactiveGraphic);
|
||||
|
||||
auto necessarySize = activePixmap.size().expandedTo(inactivePixmap.size());
|
||||
|
||||
auto wrapperWidget = new QWidget(parent);
|
||||
wrapperWidget->setFixedSize(necessarySize);
|
||||
|
||||
auto button = new PixmapButton(wrapperWidget, toolTip);
|
||||
button->setCheckable(true);
|
||||
@@ -119,6 +116,8 @@ TrackOperationsWidget::TrackOperationsWidget( TrackView * parent ) :
|
||||
button->setInactiveGraphic(inactivePixmap);
|
||||
button->setToolTip(toolTip);
|
||||
|
||||
wrapperWidget->setFixedSize(button->minimumSizeHint());
|
||||
|
||||
pixmapButton = button;
|
||||
|
||||
return wrapperWidget;
|
||||
|
||||
@@ -107,7 +107,7 @@ void PixmapButton::mouseDoubleClickEvent( QMouseEvent * _me )
|
||||
void PixmapButton::setActiveGraphic( const QPixmap & _pm )
|
||||
{
|
||||
m_activePixmap = _pm;
|
||||
resize( m_activePixmap.width(), m_activePixmap.height() );
|
||||
resize(m_activePixmap.size() / m_activePixmap.devicePixelRatio());
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,9 @@ QSize PixmapButton::sizeHint() const
|
||||
|
||||
QSize PixmapButton::minimumSizeHint() const
|
||||
{
|
||||
return m_activePixmap.size().expandedTo(m_inactivePixmap.size());
|
||||
const auto activeSize = m_activePixmap.size() / m_activePixmap.devicePixelRatio();
|
||||
const auto inactiveSize = m_inactivePixmap.size() / m_inactivePixmap.devicePixelRatio();
|
||||
return activeSize.expandedTo(inactiveSize);
|
||||
}
|
||||
|
||||
bool PixmapButton::isActive() const
|
||||
|
||||
Reference in New Issue
Block a user