File indexing completed on 2024-05-19 15:09:25

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