File indexing completed on 2024-09-08 04:17:05
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 }