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

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