QTextImageHandler: reduce code duplication

Refactor the getImage/Pixmap and getImageSize/PixmapSize functions into
templates. The functions were practically identical, and the
inconsistencies between them seem to be rather bugs or omissions than
intentional. E.g. maintaining the aspect ratio if width/height are not
specified was only implemented for the pixmap case.

Task-number: QTBUG-109212
Change-Id: Ic0de0a2d7f883c4efac97111e2c1e438f278d70d
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Santhosh Kumar <santhosh.kumar.selvaraj@qt.io>
This commit is contained in:
Volker Hilsheimer 2022-12-21 15:24:06 +01:00
parent 2d87c4d881
commit 7c84a0cd29

View File

@ -41,132 +41,68 @@ static inline QUrl fromLocalfileOrResources(QString path)
return QUrl(path);
}
static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format, const qreal devicePixelRatio = 1.0)
template<typename T>
static T getAs(QTextDocument *doc, const QTextImageFormat &format, const qreal devicePixelRatio = 1.0)
{
qreal sourcePixelRatio = 1.0;
const QString name = findAtNxFileOrResource(format.name(), devicePixelRatio, &sourcePixelRatio);
const QUrl url = fromLocalfileOrResources(name);
QPixmap pm;
const QVariant data = doc->resource(QTextDocument::ImageResource, url);
if (data.userType() == QMetaType::QPixmap || data.userType() == QMetaType::QImage) {
pm = qvariant_cast<QPixmap>(data);
} else if (data.userType() == QMetaType::QByteArray) {
pm.loadFromData(data.toByteArray());
}
T result;
if (data.userType() == QMetaType::QPixmap || data.userType() == QMetaType::QImage)
result = data.value<T>();
else if (data.metaType() == QMetaType::fromType<QByteArray>())
result.loadFromData(data.toByteArray());
if (pm.isNull()) {
QImage img;
if (name.isEmpty() || !img.load(name))
return QPixmap(":/qt-project.org/styles/commonstyle/images/file-16.png"_L1);
pm = QPixmap::fromImage(img);
doc->addResource(QTextDocument::ImageResource, url, pm);
}
if (name.contains("@2x"_L1))
pm.setDevicePixelRatio(sourcePixelRatio);
return pm;
}
static QSize getPixmapSize(QTextDocument *doc, const QTextImageFormat &format)
{
QPixmap pm;
const bool hasWidth = format.hasProperty(QTextFormat::ImageWidth);
const int width = qRound(format.width());
const bool hasHeight = format.hasProperty(QTextFormat::ImageHeight);
const int height = qRound(format.height());
QSize size(width, height);
if (!hasWidth || !hasHeight) {
pm = getPixmap(doc, format);
const QSizeF pmSize = pm.deviceIndependentSize();
if (!hasWidth) {
if (!hasHeight)
size.setWidth(pmSize.width());
else
size.setWidth(qRound(height * (pmSize.width() / (qreal) pmSize.height())));
}
if (!hasHeight) {
if (!hasWidth)
size.setHeight(pmSize.height());
else
size.setHeight(qRound(width * (pmSize.height() / (qreal) pmSize.width())));
}
}
qreal scale = 1.0;
QPaintDevice *pdev = doc->documentLayout()->paintDevice();
if (pdev) {
if (pm.isNull())
pm = getPixmap(doc, format);
if (!pm.isNull())
scale = qreal(pdev->logicalDpiY()) / qreal(qt_defaultDpi());
}
size *= scale;
return size;
}
static QImage getImage(QTextDocument *doc, const QTextImageFormat &format, const qreal devicePixelRatio = 1.0)
{
qreal sourcePixelRatio = 1.0;
const QString name = findAtNxFileOrResource(format.name(), devicePixelRatio, &sourcePixelRatio);
const QUrl url = fromLocalfileOrResources(name);
QImage image;
const QVariant data = doc->resource(QTextDocument::ImageResource, url);
if (data.userType() == QMetaType::QImage) {
image = qvariant_cast<QImage>(data);
} else if (data.userType() == QMetaType::QByteArray) {
image.loadFromData(data.toByteArray());
}
if (image.isNull()) {
if (name.isEmpty() || !image.load(name))
return QImage(":/qt-project.org/styles/commonstyle/images/file-16.png"_L1);
doc->addResource(QTextDocument::ImageResource, url, image);
if (result.isNull()) {
if (name.isEmpty() || !result.load(name))
return T(":/qt-project.org/styles/commonstyle/images/file-16.png"_L1);
doc->addResource(QTextDocument::ImageResource, url, result);
}
if (sourcePixelRatio != 1.0)
image.setDevicePixelRatio(sourcePixelRatio);
return image;
result.setDevicePixelRatio(sourcePixelRatio);
return result;
}
static QSize getImageSize(QTextDocument *doc, const QTextImageFormat &format)
template<typename T>
static QSize getSize(QTextDocument *doc, const QTextImageFormat &format)
{
QImage image;
const bool hasWidth = format.hasProperty(QTextFormat::ImageWidth);
const int width = qRound(format.width());
const bool hasHeight = format.hasProperty(QTextFormat::ImageHeight);
const int height = qRound(format.height());
T source;
QSize size(width, height);
if (!hasWidth || !hasHeight) {
image = getImage(doc, format);
QSizeF imageSize = image.deviceIndependentSize();
if (!hasWidth)
size.setWidth(imageSize.width());
if (!hasHeight)
size.setHeight(imageSize.height());
source = getAs<T>(doc, format);
const QSizeF sourceSize = source.deviceIndependentSize();
if (!hasWidth) {
if (!hasHeight)
size.setWidth(sourceSize.width());
else
size.setWidth(qRound(height * (sourceSize.width() / qreal(sourceSize.height()))));
}
if (!hasHeight) {
if (!hasWidth)
size.setHeight(sourceSize.height());
else
size.setHeight(qRound(width * (sourceSize.height() / qreal(sourceSize.width()))));
}
}
qreal scale = 1.0;
QPaintDevice *pdev = doc->documentLayout()->paintDevice();
if (pdev) {
if (image.isNull())
image = getImage(doc, format);
if (!image.isNull())
if (source.isNull())
source = getAs<T>(doc, format);
if (!source.isNull())
scale = qreal(pdev->logicalDpiY()) / qreal(qt_defaultDpi());
}
size *= scale;
return size;
}
@ -181,15 +117,15 @@ QSizeF QTextImageHandler::intrinsicSize(QTextDocument *doc, int posInDocument, c
const QTextImageFormat imageFormat = format.toImageFormat();
if (QCoreApplication::instance()->thread() != QThread::currentThread())
return getImageSize(doc, imageFormat);
return getPixmapSize(doc, imageFormat);
return getSize<QImage>(doc, imageFormat);
return getSize<QPixmap>(doc, imageFormat);
}
QImage QTextImageHandler::image(QTextDocument *doc, const QTextImageFormat &imageFormat)
{
Q_ASSERT(doc != nullptr);
return getImage(doc, imageFormat);
return getAs<QImage>(doc, imageFormat);
}
void QTextImageHandler::drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format)
@ -198,10 +134,10 @@ void QTextImageHandler::drawObject(QPainter *p, const QRectF &rect, QTextDocumen
const QTextImageFormat imageFormat = format.toImageFormat();
if (QCoreApplication::instance()->thread() != QThread::currentThread()) {
const QImage image = getImage(doc, imageFormat, p->device()->devicePixelRatio());
const QImage image = getAs<QImage>(doc, imageFormat, p->device()->devicePixelRatio());
p->drawImage(rect, image, image.rect());
} else {
const QPixmap pixmap = getPixmap(doc, imageFormat, p->device()->devicePixelRatio());
const QPixmap pixmap = getAs<QPixmap>(doc, imageFormat, p->device()->devicePixelRatio());
p->drawPixmap(rect, pixmap, pixmap.rect());
}
}