File indexing completed on 2023-09-24 04:49:58

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