File indexing completed on 2025-07-13 03:38:12

0001 /*
0002     SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org>
0003     SPDX-FileCopyrightText: 2015 Luca Beltrame <lbeltrame@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "qimageitem.h"
0009 
0010 #include <QPainter>
0011 
0012 QImageItem::QImageItem(QQuickItem *parent)
0013     : QQuickPaintedItem(parent)
0014     , m_fillMode(QImageItem::Stretch)
0015 {
0016     setFlag(ItemHasContents, true);
0017 }
0018 
0019 QImageItem::~QImageItem()
0020 {
0021 }
0022 
0023 void QImageItem::setImage(const QImage &image)
0024 {
0025     bool oldImageNull = m_image.isNull();
0026     m_image = image;
0027     updatePaintedRect();
0028     update();
0029     Q_EMIT nativeWidthChanged();
0030     Q_EMIT nativeHeightChanged();
0031     Q_EMIT imageChanged();
0032     if (oldImageNull != m_image.isNull()) {
0033         Q_EMIT nullChanged();
0034     }
0035 }
0036 
0037 QImage QImageItem::image() const
0038 {
0039     return m_image;
0040 }
0041 
0042 void QImageItem::resetImage()
0043 {
0044     setImage(QImage());
0045 }
0046 
0047 int QImageItem::nativeWidth() const
0048 {
0049     return m_image.size().width() / m_image.devicePixelRatio();
0050 }
0051 
0052 int QImageItem::nativeHeight() const
0053 {
0054     return m_image.size().height() / m_image.devicePixelRatio();
0055 }
0056 
0057 QImageItem::FillMode QImageItem::fillMode() const
0058 {
0059     return m_fillMode;
0060 }
0061 
0062 void QImageItem::setFillMode(QImageItem::FillMode mode)
0063 {
0064     if (mode == m_fillMode) {
0065         return;
0066     }
0067 
0068     m_fillMode = mode;
0069     updatePaintedRect();
0070     update();
0071     Q_EMIT fillModeChanged();
0072 }
0073 
0074 void QImageItem::paint(QPainter *painter)
0075 {
0076     if (m_image.isNull()) {
0077         return;
0078     }
0079     painter->save();
0080     painter->setRenderHint(QPainter::Antialiasing, smooth());
0081     painter->setRenderHint(QPainter::SmoothPixmapTransform, smooth());
0082 
0083     if (m_fillMode == TileVertically) {
0084         painter->scale(width() / (qreal)m_image.width(), 1);
0085     }
0086 
0087     if (m_fillMode == TileHorizontally) {
0088         painter->scale(1, height() / (qreal)m_image.height());
0089     }
0090 
0091     if (m_fillMode == Pad) {
0092         QRect centeredRect = m_paintedRect;
0093         centeredRect.moveCenter(m_image.rect().center());
0094         painter->drawImage(m_paintedRect, m_image, centeredRect);
0095     } else if (m_fillMode >= Tile) {
0096         painter->drawTiledPixmap(m_paintedRect, QPixmap::fromImage(m_image));
0097     } else {
0098         painter->drawImage(m_paintedRect, m_image, m_image.rect());
0099     }
0100 
0101     painter->restore();
0102 }
0103 
0104 bool QImageItem::isNull() const
0105 {
0106     return m_image.isNull();
0107 }
0108 
0109 int QImageItem::paintedWidth() const
0110 {
0111     if (m_image.isNull()) {
0112         return 0;
0113     }
0114 
0115     return m_paintedRect.width();
0116 }
0117 
0118 int QImageItem::paintedHeight() const
0119 {
0120     if (m_image.isNull()) {
0121         return 0;
0122     }
0123 
0124     return m_paintedRect.height();
0125 }
0126 
0127 void QImageItem::updatePaintedRect()
0128 {
0129     if (m_image.isNull()) {
0130         return;
0131     }
0132 
0133     QRectF sourceRect = m_paintedRect;
0134 
0135     QRectF destRect;
0136 
0137     switch (m_fillMode) {
0138     case PreserveAspectFit: {
0139         QSizeF scaled = m_image.size();
0140 
0141         scaled.scale(boundingRect().size(), Qt::KeepAspectRatio);
0142         destRect = QRectF(QPoint(0, 0), scaled);
0143         destRect.moveCenter(boundingRect().center().toPoint());
0144         break;
0145     }
0146     case PreserveAspectCrop: {
0147         QSizeF scaled = m_image.size();
0148 
0149         scaled.scale(boundingRect().size(), Qt::KeepAspectRatioByExpanding);
0150         destRect = QRectF(QPoint(0, 0), scaled);
0151         destRect.moveCenter(boundingRect().center().toPoint());
0152         break;
0153     }
0154     case TileVertically: {
0155         destRect = boundingRect().toRect();
0156         destRect.setWidth(destRect.width() / (width() / (qreal)m_image.width()));
0157         break;
0158     }
0159     case TileHorizontally: {
0160         destRect = boundingRect().toRect();
0161         destRect.setHeight(destRect.height() / (height() / (qreal)m_image.height()));
0162         break;
0163     }
0164     case Stretch:
0165     case Tile:
0166     case Pad:
0167     default:
0168         destRect = boundingRect().toRect();
0169     }
0170 
0171     if (destRect != sourceRect) {
0172         m_paintedRect = destRect.toRect();
0173         Q_EMIT paintedHeightChanged();
0174         Q_EMIT paintedWidthChanged();
0175     }
0176 }
0177 void QImageItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
0178 {
0179     QQuickPaintedItem::geometryChange(newGeometry, oldGeometry);
0180     updatePaintedRect();
0181 }
0182 
0183 #include "moc_qimageitem.cpp"