1 /************************************************************************ 2 * 3 * This file is part of SuperCollider Qt GUI. 4 * 5 * Copyright 2013 Jakob Leben (jakob.leben@gmail.com) 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * 20 ************************************************************************/ 21 22 #pragma once 23 24 #include <QImage> 25 #include <QPixmap> 26 #include <QPainter> 27 #include <QSharedPointer> 28 #include <QMetaType> 29 #include <cassert> 30 31 namespace QtCollider { 32 33 class Image { 34 enum State { Null, ImageState, PixmapState }; 35 36 public: Image()37 Image(): transformationMode(Qt::SmoothTransformation), m_state(Null), m_painting(false) {} 38 setImage(const QImage & image)39 void setImage(const QImage& image) { 40 assert(!m_painting); 41 m_pixmap = QPixmap(); 42 m_image = image; 43 m_state = ImageState; 44 } 45 setPixmap(const QPixmap & pixmap)46 void setPixmap(const QPixmap& pixmap) { 47 assert(!m_painting); 48 m_image = QImage(); 49 m_pixmap = pixmap; 50 m_state = PixmapState; 51 } 52 image()53 QImage& image() { 54 if (m_state == ImageState) 55 return m_image; 56 assert(!m_painting); 57 if (m_state == PixmapState) { 58 m_image = m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); 59 m_image.setDevicePixelRatio(m_pixmap.devicePixelRatio()); 60 m_pixmap = QPixmap(); 61 } 62 m_state = ImageState; 63 return m_image; 64 } 65 pixmap()66 QPixmap& pixmap() { 67 assert(!m_painting); 68 if (m_state == PixmapState) 69 return m_pixmap; 70 if (m_state == ImageState) { 71 m_pixmap = QPixmap::fromImage(m_image); 72 m_pixmap.setDevicePixelRatio(m_image.devicePixelRatio()); 73 m_image = QImage(); 74 } 75 m_state = PixmapState; 76 return m_pixmap; 77 } 78 clear()79 void clear() { 80 assert(!m_painting); 81 m_image = QImage(); 82 m_pixmap = QPixmap(); 83 m_state = Null; 84 } 85 isNull()86 bool isNull() const { return m_state == Null; } 87 width()88 int width() const { 89 switch (m_state) { 90 case ImageState: 91 return m_image.width(); 92 case PixmapState: 93 return m_pixmap.width(); 94 default: 95 return 0; 96 } 97 } 98 height()99 int height() const { 100 switch (m_state) { 101 case ImageState: 102 return m_image.height(); 103 case PixmapState: 104 return m_pixmap.height(); 105 default: 106 return 0; 107 } 108 } 109 rect()110 QRect rect() const { 111 switch (m_state) { 112 case ImageState: 113 return m_image.rect(); 114 case PixmapState: 115 return m_pixmap.rect(); 116 default: 117 return QRect(); 118 } 119 } 120 resize(const QSize & new_size,int resize_mode)121 void resize(const QSize& new_size, int resize_mode) { 122 assert(!m_painting); 123 124 if (m_state == Null) 125 return; 126 127 switch (resize_mode) { 128 case 0: { 129 if (m_state == ImageState) { 130 QImage new_image(new_size, QImage::Format_ARGB32_Premultiplied); 131 new_image.setDevicePixelRatio(m_image.devicePixelRatio()); 132 new_image.fill(Qt::transparent); 133 QPainter painter(&new_image); 134 painter.drawImage(QPointF(0, 0), m_image); 135 painter.end(); 136 m_image = new_image; 137 } else { 138 QPixmap new_pixmap(new_size); 139 new_pixmap.setDevicePixelRatio(m_pixmap.devicePixelRatio()); 140 new_pixmap.fill(Qt::transparent); 141 QPainter painter(&new_pixmap); 142 painter.drawPixmap(QPointF(0, 0), m_pixmap); 143 painter.end(); 144 m_pixmap = new_pixmap; 145 } 146 break; 147 } 148 case 1: 149 case 2: 150 case 3: { 151 Qt::AspectRatioMode aspectRatioMode = (Qt::AspectRatioMode)(resize_mode - 1); 152 if (m_state == ImageState) { 153 m_image = m_image.scaled(new_size, aspectRatioMode, transformationMode); 154 } else { 155 m_pixmap = m_pixmap.scaled(new_size, aspectRatioMode, transformationMode); 156 } 157 break; 158 } 159 default: 160 break; 161 } 162 } 163 getDevicePixelRatio()164 qreal getDevicePixelRatio() const { 165 switch (m_state) { 166 case ImageState: 167 return m_image.devicePixelRatio(); 168 case PixmapState: 169 return m_pixmap.devicePixelRatio(); 170 default: 171 return 1; 172 } 173 } 174 setDevicePixelRatio(qreal ratio)175 void setDevicePixelRatio(qreal ratio) { 176 switch (m_state) { 177 case ImageState: 178 m_image.setDevicePixelRatio(ratio); 179 case PixmapState: 180 m_pixmap.setDevicePixelRatio(ratio); 181 default: 182 break; 183 } 184 } 185 isPainting()186 bool isPainting() const { return m_painting; } setPainting(bool painting)187 void setPainting(bool painting) { m_painting = painting; } 188 189 Qt::TransformationMode transformationMode; 190 191 private: 192 QImage m_image; 193 QPixmap m_pixmap; 194 State m_state; 195 bool m_painting; 196 }; 197 198 typedef QSharedPointer<QtCollider::Image> SharedImage; 199 200 } // namespace QtCollider 201 202 Q_DECLARE_METATYPE(QtCollider::SharedImage); 203