File indexing completed on 2024-05-05 05:53:45
0001 /* 0002 This source file is part of Konsole, a terminal emulator. 0003 0004 SPDX-FileCopyrightText: 2007-2008 Robert Knight <robertknight@gmail.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 // Own 0010 #include "ColorSchemeWallpaper.h" 0011 0012 // Konsole 0013 #include "ColorScheme.h" 0014 0015 // Qt 0016 #include <QImage> 0017 #include <QImageReader> 0018 #include <QMovie> 0019 #include <QPainter> 0020 0021 using namespace Konsole; 0022 0023 ColorSchemeWallpaper::ColorSchemeWallpaper(const QString &path, 0024 const ColorSchemeWallpaper::FillStyle style, 0025 const QPointF &anchor, 0026 const qreal &opacity, 0027 const ColorSchemeWallpaper::FlipType flipType) 0028 : _path(path) 0029 , _picture(nullptr) 0030 , _movie(nullptr) 0031 , _style(style) 0032 , _anchor(anchor) 0033 , _opacity(opacity) 0034 , _flipType(flipType) 0035 , _isAnimated(false) 0036 , _frameDelay(17) // Approx. 60FPS 0037 { 0038 float x = _anchor.x(), y = _anchor.y(); 0039 0040 if (x < 0 || x > 1.0f || y < 0 || y > 1.0f) 0041 _anchor = QPointF(0.5, 0.5); 0042 } 0043 0044 ColorSchemeWallpaper::~ColorSchemeWallpaper() = default; 0045 0046 void ColorSchemeWallpaper::load() 0047 { 0048 if (_path.isEmpty()) { 0049 return; 0050 } 0051 0052 QImageReader reader(_path); 0053 _isAnimated = reader.supportsAnimation(); 0054 if (_isAnimated) { 0055 if (_movie == nullptr) { 0056 _movie = std::make_unique<QMovie>(); 0057 } 0058 0059 if (!_movie->isValid()) { 0060 _movie->setFileName(_path); 0061 _movie->start(); 0062 } 0063 0064 // Initialize _picture in load, to avoid null checking for both _picture and _movie in draw. 0065 if (_picture == nullptr) { 0066 _picture = std::make_unique<QPixmap>(); 0067 } 0068 0069 if (_picture->isNull()) { 0070 const QImage image = _movie->currentImage(); 0071 const QImage transformed = FlipImage(image, _flipType); 0072 _picture->convertFromImage(transformed); 0073 } 0074 } else { 0075 // Cleanup animated image 0076 if (_movie != nullptr) { 0077 if (_movie->isValid()) { 0078 _movie->stop(); 0079 } 0080 _movie.reset(); 0081 } 0082 0083 // Create and load original pixmap 0084 if (_picture == nullptr) { 0085 _picture = std::make_unique<QPixmap>(); 0086 } 0087 0088 if (_picture->isNull()) { 0089 const QImage image(_path); 0090 const QImage transformed = FlipImage(image, _flipType); 0091 _picture->convertFromImage(transformed); 0092 } 0093 } 0094 } 0095 0096 bool ColorSchemeWallpaper::isNull() const 0097 { 0098 return _path.isEmpty(); 0099 } 0100 0101 bool ColorSchemeWallpaper::draw(QPainter &painter, const QRect rect, qreal bgColorOpacity, const QColor &backgroundColor) 0102 { 0103 if ((_picture == nullptr) || _picture->isNull()) { 0104 return false; 0105 } 0106 0107 painter.save(); 0108 painter.setCompositionMode(QPainter::CompositionMode_SourceOver); 0109 painter.setOpacity(bgColorOpacity); 0110 painter.fillRect(rect, backgroundColor); 0111 painter.setOpacity(_opacity); 0112 0113 if (_isAnimated) { 0114 if (_movie->state() == QMovie::NotRunning) { 0115 _movie->start(); 0116 } 0117 if (_picture != nullptr) { 0118 _picture.reset(); 0119 } 0120 if (_picture == nullptr) { 0121 _picture = std::make_unique<QPixmap>(); 0122 } 0123 if (_picture->isNull()) { 0124 QImage currentImage = _movie->currentImage(); 0125 const QImage transformed = FlipImage(currentImage, _flipType); 0126 _picture->convertFromImage(transformed); 0127 } 0128 } 0129 if (_style == Tile) { 0130 painter.drawTiledPixmap(rect, *_picture, rect.topLeft()); 0131 } else { 0132 QRectF srcRect = ScaledRect(painter.viewport().size(), _picture->size(), rect); 0133 painter.drawPixmap(rect, *_picture, srcRect); 0134 } 0135 0136 painter.restore(); 0137 0138 return true; 0139 } 0140 0141 QString ColorSchemeWallpaper::path() const 0142 { 0143 return _path; 0144 } 0145 0146 ColorSchemeWallpaper::FillStyle ColorSchemeWallpaper::style() const 0147 { 0148 return _style; 0149 } 0150 0151 ColorSchemeWallpaper::FlipType ColorSchemeWallpaper::flipType() const 0152 { 0153 return _flipType; 0154 } 0155 0156 QPointF ColorSchemeWallpaper::anchor() const 0157 { 0158 return _anchor; 0159 } 0160 0161 qreal ColorSchemeWallpaper::opacity() const 0162 { 0163 return _opacity; 0164 } 0165 0166 QRectF ColorSchemeWallpaper::ScaledRect(const QSize viewportSize, const QSize pictureSize, const QRect rect) 0167 { 0168 QRectF scaledRect = QRectF(); 0169 QSize scaledSize = _style == NoScaling ? pictureSize : pictureSize.scaled(viewportSize, RatioMode()); 0170 0171 double scaleX = pictureSize.width() / static_cast<double>(scaledSize.width()); 0172 double scaleY = pictureSize.height() / static_cast<double>(scaledSize.height()); 0173 0174 double offsetX = (scaledSize.width() - viewportSize.width()) * _anchor.x(); 0175 double offsetY = (scaledSize.height() - viewportSize.height()) * _anchor.y(); 0176 0177 scaledRect.setX((rect.x() + offsetX) * scaleX); 0178 scaledRect.setY((rect.y() + offsetY) * scaleY); 0179 0180 scaledRect.setWidth(rect.width() * scaleX); 0181 scaledRect.setHeight(rect.height() * scaleY); 0182 0183 return scaledRect; 0184 } 0185 0186 Qt::AspectRatioMode ColorSchemeWallpaper::RatioMode() 0187 { 0188 switch (_style) { 0189 case Crop: 0190 return Qt::KeepAspectRatioByExpanding; 0191 case Adapt: 0192 return Qt::KeepAspectRatio; 0193 case Tile: 0194 case Stretch: 0195 default: 0196 return Qt::IgnoreAspectRatio; 0197 } 0198 } 0199 0200 QImage ColorSchemeWallpaper::FlipImage(const QImage image, const ColorSchemeWallpaper::FlipType flipType) 0201 { 0202 switch (flipType) { 0203 case Horizontal: 0204 return image.mirrored(true, false); 0205 case Vertical: 0206 return image.mirrored(false, true); 0207 case Both: 0208 return image.mirrored(true, true); 0209 default: 0210 return image; 0211 } 0212 } 0213 0214 bool ColorSchemeWallpaper::isAnimated() const 0215 { 0216 return _isAnimated; 0217 } 0218 0219 int ColorSchemeWallpaper::getFrameDelay() const 0220 { 0221 return _frameDelay; 0222 } 0223 0224 #include "moc_ColorSchemeWallpaper.cpp"