Commit a2afa3a6 authored by Prince Gupta's avatar Prince Gupta Committed by Jean-Baptiste Kempf
Browse files

qt/roundimage: use QImageReader

parent ecbe4ea6
......@@ -27,13 +27,12 @@
#include "roundimage.hpp"
#include <QBrush>
#include <QBuffer>
#include <QImage>
#include <QImageReader>
#include <QPainter>
#include <QPainterPath>
#include <QPen>
#include <QQuickWindow>
#include <QSvgRenderer>
#include <QGuiApplication>
#ifdef QT_NETWORK_LIB
......@@ -44,16 +43,6 @@
namespace
{
class Image
{
public:
static std::unique_ptr<Image> getImage(const QUrl &source, const QSizeF &sourceSize);
virtual ~Image() = default;
// must be reentrant
virtual void paint(QPainter *painter, const QSizeF &size) = 0;
};
QString getPath(const QUrl &url)
{
QString path = url.isLocalFile() ? url.toLocalFile() : url.toString();
......@@ -62,7 +51,7 @@ namespace
return path;
}
QByteArray readFile(const QUrl &url)
std::unique_ptr<QIODevice> getReadable(const QUrl &url)
{
#ifdef QT_NETWORK_LIB
if (url.scheme() == "http" || url.scheme() == "https")
......@@ -73,16 +62,34 @@ namespace
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
return reply->readAll();
class DataOwningBuffer : public QBuffer
{
public:
DataOwningBuffer(const QByteArray &data) : m_data {data}
{
setBuffer(&m_data);
}
~DataOwningBuffer()
{
close();
setBuffer(nullptr);
}
private:
QByteArray m_data;
};
auto file = std::make_unique<DataOwningBuffer>(reply->readAll());
file->open(QIODevice::ReadOnly);
return file;
}
#endif
QByteArray data;
QString path = getPath(url);
QFile file(path);
if (file.open(QIODevice::ReadOnly))
data = file.readAll();
return data;
auto file = std::make_unique<QFile>(getPath(url));
file->open(QIODevice::ReadOnly);
return file;
}
}
......@@ -210,6 +217,23 @@ QImage RoundImage::RoundImageGenerator::execute()
if (width <= 0 || height <= 0)
return {};
auto file = getReadable(source);
if (!file || !file->isOpen())
return {};
QImageReader sourceReader(file.get());
// do PreserveAspectCrop
const QSizeF size {width, height};
QSizeF defaultSize = sourceReader.size();
if (!defaultSize.isValid())
defaultSize = size;
const qreal ratio = std::max(size.width() / defaultSize.width(), size.height() / defaultSize.height());
const QSizeF targetSize = defaultSize * ratio;
const QPointF alignedCenteredTopLeft {(size.width() - targetSize.width()) / 2., (size.height() - targetSize.height()) / 2.};
sourceReader.setScaledSize(targetSize.toSize());
QImage target(width, height, QImage::Format_ARGB32);
if (target.isNull())
return target;
......@@ -225,76 +249,8 @@ QImage RoundImage::RoundImageGenerator::execute()
path.addRoundedRect(0, 0, width, height, radius, radius);
painter.setClipPath(path);
auto image = Image::getImage(source, {width, height});
image->paint(&painter, {width, height});
painter.drawImage({alignedCenteredTopLeft, targetSize}, sourceReader.read());
painter.end();
return target;
}
std::unique_ptr<Image> Image::getImage(const QUrl &source, const QSizeF &sourceSize)
{
class QtImage : public Image
{
public:
QtImage(const QByteArray &data, const QSizeF &sourceSize)
{
m_image.loadFromData(data);
if (sourceSize.isValid())
m_image = m_image.scaled(sourceSize.toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
void paint(QPainter *painter, const QSizeF &size) override
{
if (m_image.isNull() || !painter || !size.isValid())
return;
auto image = m_image;
// do PreserveAspectCrop
const qreal ratio = std::max(qreal(size.width()) / image.width(), qreal(size.height()) / image.height());
if (ratio != 0.0)
image = image.scaled(qRound(image.width() * ratio), qRound(image.height() * ratio),
Qt::IgnoreAspectRatio, // aspect ratio handled manually by using `ratio`
Qt::SmoothTransformation);
const QPointF alignedCenteredTopLeft {(size.width() - image.width()) / 2, (size.height() - image.height()) / 2};
painter->drawImage(alignedCenteredTopLeft, image);
}
private:
QImage m_image;
};
class SVGImage : public Image
{
public:
SVGImage(const QByteArray &data)
{
m_svg.load(data);
}
void paint(QPainter *painter, const QSizeF &size) override
{
if (!m_svg.isValid() || !painter || !size.isValid())
return;
// do PreserveAspectCrop
const QSizeF defaultSize = m_svg.defaultSize();
const qreal ratio = std::max(size.width() / defaultSize.width(), size.height() / defaultSize.height());
const QSizeF targetSize = defaultSize * ratio;
const QPointF alignedCenteredTopLeft {(size.width() - targetSize.width()) / 2., (size.height() - targetSize.height()) / 2.};
m_svg.render(painter, QRectF {alignedCenteredTopLeft, targetSize});
}
private:
QSvgRenderer m_svg;
};
const QByteArray data = readFile(source);
if (source.toString().endsWith(".svg"))
return std::make_unique<SVGImage>(data);
return std::make_unique<QtImage>(data, sourceSize);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment